tests/integration/sqlite-vec.test.ts
Rama main · réplica de lectura del repositorio original.
import { afterAll, beforeAll, test } from "bun:test";
import assert from "node:assert/strict";
import { mkdtempSync, rmSync, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createApp } from "../../src/core/app";
import { migrate } from "../../src/core/migrations";
import { embeddingPolicyFingerprint } from "../../src/core/vectors";
import { createSqliteDb, openDatabase } from "../../src/runtime/bun/sqlite";
import { createSqliteVecStore, createHttpEmbedder } from "../../src/runtime/bun/vectors";
import { clientVia, provisionWith } from "../contract/harness";
/**
* The real sqlite-vec store, not a stub.
*
* The contract-level vector test uses an in-memory fake to exercise the shared
* core's hybrid branch. This one loads the actual extension and runs real
* nearest-neighbour search, so a change that breaks the native binding, the
* vector encoding, or the distance-to-score conversion fails here.
*
* Skips itself when the platform has no prebuilt extension, which is the same
* condition under which the service degrades to FTS.
*/
const directory = mkdtempSync(join(tmpdir(), "titen-realvec-"));
const DIMENSIONS = 4;
const store = createSqliteVecStore(join(directory, "vec.db"), DIMENSIONS);
const available = store !== null;
/** Deterministic stand-in for a model: distinct unit vectors per axis. */
const axis = (index: number) => {
const vector = new Float32Array(DIMENSIONS);
vector[index % DIMENSIONS] = 1;
return vector;
};
const metadata = (org_id: string, subject_id = "subject", project_id = "") => ({
org_id,
subject_id,
project_id,
});
afterAll(() => {
rmSync(directory, { recursive: true, force: true });
});
test("the prebuilt extension is present on this platform", () => {
assert.equal(
available,
true,
"sqlite-vec did not load; vector retrieval would degrade to FTS here",
);
});
test("nearest-neighbour search returns the closest vector first", async () => {
if (!available) return;
await store!.upsert([
{ id: "claim_a", vector: axis(0), metadata: metadata("org") },
{ id: "claim_b", vector: axis(1), metadata: metadata("org") },
{ id: "claim_c", vector: axis(2), metadata: metadata("org") },
]);
const hits = await store!.query(axis(1), { topK: 3 });
assert.equal(hits.length, 3);
assert.equal(hits[0]!.id, "claim_b", "the exact match must rank first");
assert.equal(hits[0]!.score, 1, "an exact match scores 1 at distance 0");
assert.ok(
hits[1]!.score < hits[0]!.score,
"score must decrease as distance grows",
);
});
test("an upsert replaces a vector rather than duplicating its id", async () => {
if (!available) return;
await store!.upsert([
{ id: "claim_move", vector: axis(0), metadata: metadata("org") },
]);
const before = await store!.query(axis(0), { topK: 5 });
const beforeCount = before.filter((h) => h.id === "claim_move").length;
assert.equal(beforeCount, 1);
// Same id, different direction: it must move, not appear twice.
await store!.upsert([
{ id: "claim_move", vector: axis(3), metadata: metadata("org") },
]);
const near = await store!.query(axis(3), { topK: 5 });
assert.equal(near.filter((h) => h.id === "claim_move").length, 1, "no duplicate id");
assert.equal(near[0]!.id, "claim_move", "it must now be nearest to its new direction");
});
test("removal takes a vector out of results", async () => {
if (!available) return;
await store!.upsert([
{ id: "claim_gone", vector: axis(2), metadata: metadata("org") },
]);
assert.ok((await store!.query(axis(2), { topK: 5 })).some((h) => h.id === "claim_gone"));
await store!.remove(["claim_gone"]);
assert.ok(
!(await store!.query(axis(2), { topK: 5 })).some((h) => h.id === "claim_gone"),
"a removed vector must not be returned",
);
});
test("scope metadata filters before the nearest-neighbour limit", async () => {
if (!available) return;
const foreign = Array.from({ length: 24 }, (_, index) => ({
id: `foreign_${index}`,
vector: axis(0),
metadata: metadata("foreign", "same-subject"),
}));
await store!.upsert([
...foreign,
{
id: "authorized",
vector: new Float32Array([0.9, 0.1, 0, 0]),
metadata: metadata("authorized", "same-subject"),
},
]);
const hits = await store!.query(axis(0), {
topK: 1,
filter: { org_id: "authorized", subject_id: "same-subject" },
});
assert.deepEqual(hits.map((hit) => hit.id), ["authorized"]);
});
test("vectors live outside the canonical database", () => {
if (!available) return;
assert.ok(
existsSync(join(directory, "vec.db")),
"the index must be its own file so it stays rebuildable",
);
});
test("an embedder whose dimensions disagree fails loudly", async () => {
// A silent mismatch degrades retrieval quality invisibly, which is worse than
// an error, so the provider checks what the endpoint actually returned.
const server = Bun.serve({
port: 0,
hostname: "127.0.0.1",
fetch: () =>
new Response(JSON.stringify({ data: [{ embedding: [1, 0] }] }), {
headers: { "content-type": "application/json" },
}),
});
const embedder = createHttpEmbedder({
baseUrl: `http://127.0.0.1:${server.port}/v1`,
model: "stub",
dimensions: DIMENSIONS,
});
await assert.rejects(
() => embedder.embed(["anything"]),
/Invalid embedding response/,
);
server.stop(true);
});
test("the real store drives compilation through the shared core", async () => {
if (!available) return;
const dbPath = join(directory, "titen.db");
const handle = openDatabase(dbPath);
const db = createSqliteDb(handle);
await migrate(db);
const provisioned = await provisionWith(db, { scopes: ["*"] });
// A local embedding endpoint, so no network or model is required.
const embeddings = new Map<string, Float32Array>();
const server = Bun.serve({
port: 0,
hostname: "127.0.0.1",
async fetch(request: Request) {
const { input } = (await request.json()) as { input: string[] };
return Response.json({
data: input.map((text) => ({
embedding: [...(embeddings.get(text) ?? axis(0))],
})),
});
},
});
const capability = {
store: store!,
fingerprint: {
provider: "integration",
model: "stub",
revision: "v1",
dimensions: DIMENSIONS,
metric: "cosine",
preprocessing: embeddingPolicyFingerprint("raw-unit-v1", 0.1),
index_schema: "claims-scope-v1",
},
embedder: createHttpEmbedder({
baseUrl: `http://127.0.0.1:${server.port}/v1`,
model: "stub",
dimensions: DIMENSIONS,
}),
};
const client = clientVia(
createApp({ db, revision: "realvec", runtime: "bun-sqlite", vectors: capability }),
"http://titen.test",
);
const ready = await client.call("GET", "/readyz");
assert.equal(ready.body.data.capabilities.vector, "enabled");
const observation = await client.call("POST", "/v1/observations", {
key: provisioned.key,
body: {
subject_id: "user_realvec",
kind: "tool_result",
content: "Rollback rehearsal evidence for the release gate.",
source: { type: "tool", ref: "realvec#1" },
trust: "verified",
},
});
assert.equal(observation.status, 201);
const consolidated = await client.call("POST", "/v1/consolidations", {
key: provisioned.key,
body: {
subject_id: "user_realvec",
claims: [
{
kind: "procedural",
statement: "Release requires a rollback rehearsal.",
sources: [
{ observation_id: observation.body.data.observation_id, relation: "supports" },
],
},
],
},
});
assert.equal(consolidated.status, 201);
const claimId = consolidated.body.data.claims[0].claim_id as string;
// Index the claim, and point the query at the same direction.
const task = "release rollback rehearsal";
embeddings.set(task, axis(1));
await store!.upsert([
{
id: claimId,
vector: axis(1),
metadata: metadata(provisioned.orgId, "user_realvec"),
},
]);
const compiled = await client.call("POST", "/v1/context/compile", {
key: provisioned.key,
body: { subject_id: "user_realvec", task, max_tokens: 900 },
});
assert.equal(compiled.status, 200);
assert.equal(compiled.body.meta.degraded.vector, "used");
const item = compiled.body.data.items.find((i: any) => i.claim_id === claimId);
assert.ok(item, "the indexed claim must be compiled");
assert.equal(
item.score_components.relevance,
1,
"an exact vector match must reach full relevance",
);
server.stop(true);
handle.close();
});