mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
feat(authority): add Trivium vector primary adapter
This commit is contained in:
174
tests/authority-vector-primary.mjs
Normal file
174
tests/authority-vector-primary.mjs
Normal file
@@ -0,0 +1,174 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { addEdge, addNode, createEdge, createEmptyGraph, createNode } from "../graph/graph.js";
|
||||
import {
|
||||
installResolveHooks,
|
||||
toDataModuleUrl,
|
||||
} from "./helpers/register-hooks-compat.mjs";
|
||||
|
||||
installResolveHooks([
|
||||
{
|
||||
specifiers: ["../../../../../script.js"],
|
||||
url: toDataModuleUrl("export function getRequestHeaders() { return {}; }"),
|
||||
},
|
||||
{
|
||||
specifiers: ["../../../../extensions.js"],
|
||||
url: toDataModuleUrl("export const extension_settings = { st_bme: {} };"),
|
||||
},
|
||||
]);
|
||||
|
||||
const {
|
||||
findSimilarNodesByText,
|
||||
isAuthorityVectorConfig,
|
||||
normalizeAuthorityVectorConfig,
|
||||
syncGraphVectorIndex,
|
||||
} = await import("../vector/vector-index.js");
|
||||
|
||||
function createAuthorityVectorGraph() {
|
||||
const graph = createEmptyGraph();
|
||||
graph.historyState.chatId = "chat-authority-vector";
|
||||
const first = createNode({
|
||||
type: "event",
|
||||
fields: { summary: "Alice finds the silver key" },
|
||||
seq: 1,
|
||||
});
|
||||
first.id = "node-a";
|
||||
first.embedding = [0.1, 0.2];
|
||||
const second = createNode({
|
||||
type: "event",
|
||||
fields: { summary: "Bob guards the archive door" },
|
||||
seq: 2,
|
||||
});
|
||||
second.id = "node-b";
|
||||
second.embedding = [0.2, 0.3];
|
||||
addNode(graph, first);
|
||||
addNode(graph, second);
|
||||
addEdge(
|
||||
graph,
|
||||
createEdge({
|
||||
fromId: first.id,
|
||||
toId: second.id,
|
||||
relation: "related",
|
||||
strength: 0.75,
|
||||
}),
|
||||
);
|
||||
return { graph, first, second };
|
||||
}
|
||||
|
||||
function createMockTriviumClient({ failBulkUpsert = false } = {}) {
|
||||
const calls = [];
|
||||
return {
|
||||
calls,
|
||||
async purge(payload) {
|
||||
calls.push(["purge", payload]);
|
||||
return { ok: true };
|
||||
},
|
||||
async bulkUpsert(payload) {
|
||||
calls.push(["bulkUpsert", payload]);
|
||||
if (failBulkUpsert) {
|
||||
throw new Error("trivium-down");
|
||||
}
|
||||
return { ok: true, upserted: payload.items?.length || 0 };
|
||||
},
|
||||
async deleteMany(payload) {
|
||||
calls.push(["deleteMany", payload]);
|
||||
return { ok: true };
|
||||
},
|
||||
async linkMany(payload) {
|
||||
calls.push(["linkMany", payload]);
|
||||
return { ok: true, linked: payload.links?.length || 0 };
|
||||
},
|
||||
async search(payload) {
|
||||
calls.push(["search", payload]);
|
||||
return {
|
||||
results: [
|
||||
{ nodeId: "node-b", score: 0.91 },
|
||||
{ nodeId: "node-outside", score: 0.88 },
|
||||
],
|
||||
};
|
||||
},
|
||||
async stat(payload) {
|
||||
calls.push(["stat", payload]);
|
||||
return { ok: true };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const config = normalizeAuthorityVectorConfig({
|
||||
authorityBaseUrl: "/api/plugins/authority",
|
||||
authorityVectorSyncChunkSize: 1,
|
||||
authorityVectorFailOpen: true,
|
||||
});
|
||||
assert.equal(isAuthorityVectorConfig(config), true);
|
||||
|
||||
{
|
||||
const { graph, first, second } = createAuthorityVectorGraph();
|
||||
const triviumClient = createMockTriviumClient();
|
||||
const result = await syncGraphVectorIndex(graph, config, {
|
||||
chatId: "chat-authority-vector",
|
||||
purge: true,
|
||||
triviumClient,
|
||||
});
|
||||
|
||||
assert.equal(graph.vectorIndexState.mode, "authority");
|
||||
assert.equal(graph.vectorIndexState.source, "authority-trivium");
|
||||
assert.equal(graph.vectorIndexState.dirty, false);
|
||||
assert.equal(graph.vectorIndexState.lastWarning, "");
|
||||
assert.equal(result.insertedHashes.length, 2);
|
||||
assert.equal(result.stats.indexed, 2);
|
||||
assert.equal(result.stats.pending, 0);
|
||||
assert.equal(first.embedding, null);
|
||||
assert.equal(second.embedding, null);
|
||||
assert.equal(triviumClient.calls.filter(([name]) => name === "purge").length, 1);
|
||||
const upserts = triviumClient.calls.filter(([name]) => name === "bulkUpsert");
|
||||
assert.equal(upserts.length, 2);
|
||||
assert.deepEqual(
|
||||
upserts.flatMap(([, payload]) => payload.items.map((item) => item.nodeId)).sort(),
|
||||
["node-a", "node-b"],
|
||||
);
|
||||
const linkCall = triviumClient.calls.find(([name]) => name === "linkMany");
|
||||
assert.equal(linkCall?.[1]?.links?.[0]?.fromId, "node-a");
|
||||
assert.equal(linkCall?.[1]?.links?.[0]?.toId, "node-b");
|
||||
}
|
||||
|
||||
{
|
||||
const { graph, first, second } = createAuthorityVectorGraph();
|
||||
const triviumClient = createMockTriviumClient();
|
||||
const queryConfig = { ...config, triviumClient };
|
||||
await syncGraphVectorIndex(graph, queryConfig, {
|
||||
chatId: "chat-authority-vector",
|
||||
purge: true,
|
||||
triviumClient,
|
||||
});
|
||||
|
||||
const results = await findSimilarNodesByText(
|
||||
graph,
|
||||
"archive door",
|
||||
queryConfig,
|
||||
5,
|
||||
[first, second],
|
||||
);
|
||||
|
||||
assert.deepEqual(results, [{ nodeId: "node-b", score: 0.91 }]);
|
||||
const searchCall = triviumClient.calls.find(([name]) => name === "search");
|
||||
assert.deepEqual(searchCall?.[1]?.candidateIds.sort(), ["node-a", "node-b"]);
|
||||
assert.equal(graph.vectorIndexState.lastSearchTimings.mode, "authority");
|
||||
assert.equal(graph.vectorIndexState.lastSearchTimings.success, true);
|
||||
}
|
||||
|
||||
{
|
||||
const { graph } = createAuthorityVectorGraph();
|
||||
const triviumClient = createMockTriviumClient({ failBulkUpsert: true });
|
||||
const result = await syncGraphVectorIndex(graph, config, {
|
||||
chatId: "chat-authority-vector",
|
||||
purge: true,
|
||||
triviumClient,
|
||||
});
|
||||
|
||||
assert.match(result.error, /trivium-down/);
|
||||
assert.equal(graph.vectorIndexState.mode, "authority");
|
||||
assert.equal(graph.vectorIndexState.dirty, true);
|
||||
assert.equal(graph.vectorIndexState.dirtyReason, "authority-trivium-sync-failed");
|
||||
assert.match(graph.vectorIndexState.lastWarning, /Authority Trivium 同步失败/);
|
||||
}
|
||||
|
||||
console.log("authority-vector-primary tests passed");
|
||||
Reference in New Issue
Block a user