cozo-memory 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +533 -0
  3. package/dist/api_bridge.js +266 -0
  4. package/dist/benchmark-gpu-cpu.js +188 -0
  5. package/dist/benchmark-heavy.js +230 -0
  6. package/dist/benchmark.js +160 -0
  7. package/dist/clear-cache.js +29 -0
  8. package/dist/db-service.js +228 -0
  9. package/dist/download-model.js +48 -0
  10. package/dist/embedding-service.js +249 -0
  11. package/dist/full-system-test.js +45 -0
  12. package/dist/hybrid-search.js +337 -0
  13. package/dist/index.js +3106 -0
  14. package/dist/inference-engine.js +348 -0
  15. package/dist/memory-service.js +215 -0
  16. package/dist/test-advanced-filters.js +64 -0
  17. package/dist/test-advanced-search.js +82 -0
  18. package/dist/test-advanced-time.js +47 -0
  19. package/dist/test-embedding.js +22 -0
  20. package/dist/test-filter-expr.js +84 -0
  21. package/dist/test-fts.js +58 -0
  22. package/dist/test-functions.js +25 -0
  23. package/dist/test-gpu-check.js +16 -0
  24. package/dist/test-graph-algs-final.js +76 -0
  25. package/dist/test-graph-filters.js +88 -0
  26. package/dist/test-graph-rag.js +124 -0
  27. package/dist/test-graph-walking.js +138 -0
  28. package/dist/test-index.js +35 -0
  29. package/dist/test-int-filter.js +48 -0
  30. package/dist/test-integration.js +69 -0
  31. package/dist/test-lower.js +35 -0
  32. package/dist/test-lsh.js +67 -0
  33. package/dist/test-mcp-tool.js +40 -0
  34. package/dist/test-pagerank.js +31 -0
  35. package/dist/test-semantic-walk.js +145 -0
  36. package/dist/test-time-filter.js +66 -0
  37. package/dist/test-time-functions.js +38 -0
  38. package/dist/test-triggers.js +60 -0
  39. package/dist/test-ts-ort.js +48 -0
  40. package/dist/test-validity-access.js +35 -0
  41. package/dist/test-validity-body.js +42 -0
  42. package/dist/test-validity-decomp.js +37 -0
  43. package/dist/test-validity-extraction.js +45 -0
  44. package/dist/test-validity-json.js +35 -0
  45. package/dist/test-validity.js +38 -0
  46. package/dist/types.js +3 -0
  47. package/dist/verify-gpu.js +30 -0
  48. package/dist/verify_transaction_tool.js +46 -0
  49. package/package.json +75 -0
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ async function main() {
5
+ const memory = new index_1.MemoryServer();
6
+ // Wait for initialization
7
+ await memory.initPromise;
8
+ console.log("--- Adding Test Data ---");
9
+ const alice = await memory.createEntity({
10
+ name: "Alice",
11
+ type: "Person",
12
+ metadata: { role: "engineer", expertise: "TypeScript" }
13
+ });
14
+ const bob = await memory.createEntity({
15
+ name: "Bob",
16
+ type: "Person",
17
+ metadata: { role: "manager", expertise: "Agile" }
18
+ });
19
+ const projectX = await memory.createEntity({
20
+ name: "Project X",
21
+ type: "Project",
22
+ metadata: { status: "Active" }
23
+ });
24
+ // Use id instead of entity_id
25
+ await memory.createRelation({
26
+ from_id: alice.id,
27
+ to_id: projectX.id,
28
+ relation_type: "WORKS_ON",
29
+ });
30
+ await memory.createRelation({
31
+ from_id: bob.id,
32
+ to_id: projectX.id,
33
+ relation_type: "WORKS_ON",
34
+ });
35
+ await memory.addObservation({
36
+ entity_id: alice.id,
37
+ text: "Alice is a software engineer working on Project X.",
38
+ });
39
+ await memory.addObservation({
40
+ entity_id: bob.id,
41
+ text: "Bob is a project manager for Project X.",
42
+ });
43
+ console.log("Entities created:", { alice: alice.id, bob: bob.id, projectX: projectX.id });
44
+ console.log("\n--- Search 1: Simple Search for Alice ---");
45
+ // Use advancedSearch
46
+ const res1 = await memory.advancedSearch({
47
+ query: "Alice engineer",
48
+ limit: 5,
49
+ });
50
+ console.log("Results 1:", JSON.stringify(res1, null, 2));
51
+ console.log("\n--- Search 2: Filter by Type 'Person' ---");
52
+ const res2 = await memory.advancedSearch({
53
+ query: "engineer",
54
+ filters: {
55
+ entityTypes: ["Person"],
56
+ },
57
+ });
58
+ console.log("Results 2:", JSON.stringify(res2, null, 2));
59
+ console.log("\n--- Search 3: Filter by Metadata ---");
60
+ const res3 = await memory.advancedSearch({
61
+ query: "Alice",
62
+ filters: {
63
+ metadata: {
64
+ role: "engineer",
65
+ },
66
+ },
67
+ });
68
+ console.log("Results 3:", JSON.stringify(res3, null, 2));
69
+ console.log("\n--- Search 4: Graph Constraints (Relations) ---");
70
+ // Find people who work on Project X
71
+ const res4 = await memory.advancedSearch({
72
+ query: "Project X",
73
+ graphConstraints: {
74
+ requiredRelations: ["WORKS_ON"],
75
+ maxDepth: 1,
76
+ },
77
+ });
78
+ console.log("Results 4:", JSON.stringify(res4, null, 2));
79
+ }
80
+ main().catch((error) => {
81
+ console.log("Error in test:", error);
82
+ });
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cozo_node_1 = require("cozo-node");
7
+ const hybrid_search_1 = require("./hybrid-search");
8
+ const embedding_service_1 = require("./embedding-service");
9
+ const fs_1 = __importDefault(require("fs"));
10
+ async function testAdvancedSearchTime() {
11
+ const dbPath = "test-advanced-time.db";
12
+ if (fs_1.default.existsSync(dbPath)) {
13
+ try {
14
+ fs_1.default.unlinkSync(dbPath);
15
+ }
16
+ catch (e) { }
17
+ }
18
+ const db = new cozo_node_1.CozoDb("sqlite", dbPath);
19
+ const embeddingService = new embedding_service_1.EmbeddingService(); // Assuming it works with default or mock
20
+ // Setup schema
21
+ const EMBEDDING_DIM = 1024;
22
+ await db.run(`{:create entity {id: String, created_at: Validity => name: String, type: String, embedding: <F32; ${EMBEDDING_DIM}>, metadata: Json}}`);
23
+ await db.run(`{::hnsw create entity:semantic {dim: ${EMBEDDING_DIM}, m: 16, dtype: F32, fields: [embedding], distance: Cosine, ef_construction: 200}}`);
24
+ await db.run(`{:create entity_rank {entity_id: String => pagerank: Float}}`);
25
+ const hybridSearch = new hybrid_search_1.HybridSearch(db, embeddingService);
26
+ // Insert some data
27
+ const now = Date.now();
28
+ const vec = new Array(EMBEDDING_DIM).fill(0.1);
29
+ const data = [
30
+ ['id1', [now - 10000000, true], 'Old Entity', 'typeA', vec, {}],
31
+ ['id2', [now, true], 'New Entity', 'typeB', vec, {}]
32
+ ];
33
+ await db.run(`?[id, created_at, name, type, embedding, metadata] <- $data :put entity {id, created_at => name, type, embedding, metadata}`, { data });
34
+ await db.run(`?[entity_id, pagerank] <- [['id1', 0.5], ['id2', 0.5]] :put entity_rank {entity_id => pagerank}`);
35
+ console.log("--- Testing Advanced Search with Time Filter ---");
36
+ try {
37
+ const results = await hybridSearch.advancedSearch({
38
+ query: "test",
39
+ timeRangeHours: 1 // Only new entity should match
40
+ });
41
+ console.log("Results:", results.map(r => r.id));
42
+ }
43
+ catch (e) {
44
+ console.error("Advanced Search Error:", e.message || e);
45
+ }
46
+ }
47
+ testAdvancedSearchTime();
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const embedding_service_1 = require("./embedding-service");
4
+ async function main() {
5
+ console.log("Starting Embedding Test...");
6
+ const service = new embedding_service_1.EmbeddingService();
7
+ try {
8
+ console.log("Generating embedding for 'Hello World'...");
9
+ const vec = await service.embed("Hello World");
10
+ console.log("Embedding vector length:", vec.length);
11
+ // Check if all are 0
12
+ const isAllZero = vec.every(v => v === 0);
13
+ console.log("Is vector only zeros?", isAllZero);
14
+ if (!isAllZero) {
15
+ console.log("First 5 values:", vec.slice(0, 5));
16
+ }
17
+ }
18
+ catch (e) {
19
+ console.error("Error in test:", e);
20
+ }
21
+ }
22
+ main();
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cozo_node_1 = require("cozo-node");
7
+ const fs_1 = __importDefault(require("fs"));
8
+ async function testFilterExpr() {
9
+ const dbPath = "test-filter.db";
10
+ if (fs_1.default.existsSync(dbPath)) {
11
+ try {
12
+ fs_1.default.unlinkSync(dbPath);
13
+ }
14
+ catch (e) { }
15
+ }
16
+ const db = new cozo_node_1.CozoDb("sqlite", dbPath);
17
+ const EMBEDDING_DIM = 1536;
18
+ try {
19
+ console.log("Creating table (type as PK)...");
20
+ await db.run(`{:create test_entity {id: String, type: String => metadata: Json, embedding: <F32; ${EMBEDDING_DIM}>}}`);
21
+ console.log("Creating HNSW index...");
22
+ await db.run(`{::hnsw create test_entity:semantic {dim: ${EMBEDDING_DIM}, m: 16, dtype: F32, fields: [embedding], distance: Cosine, ef_construction: 200}}`);
23
+ const vec1 = new Array(EMBEDDING_DIM).fill(0.1);
24
+ const vec2 = new Array(EMBEDDING_DIM).fill(0.9);
25
+ console.log("Inserting data...");
26
+ const data = [
27
+ ['id1', 'typeA', { status: 'active' }, vec1],
28
+ ['id2', 'typeB', { status: 'inactive' }, vec2]
29
+ ];
30
+ await db.run(`
31
+ ?[id, type, metadata, embedding] <- $data
32
+ :put test_entity {id, type => metadata, embedding}
33
+ `, { data });
34
+ console.log("Data inserted.");
35
+ console.log("--- Test: Filter with type (requesting it) ---");
36
+ try {
37
+ const res = await db.run(`
38
+ ?[id, type] := ~test_entity:semantic{id, type | query: vec($vec1), k: 2, ef: 100, filter: type == 'typeA'}
39
+ `, { vec1 });
40
+ console.log("Results (type == 'typeA'):", res.rows);
41
+ }
42
+ catch (e) {
43
+ console.error("Error (type == 'typeA'):", e.message || e);
44
+ }
45
+ console.log("--- Test: Filter with parameter (type in output) ---");
46
+ try {
47
+ const res = await db.run(`
48
+ ?[id, type] := ~test_entity:semantic{id, type | query: vec($vec1), k: 2, ef: 100, filter: type == $allowed_type}
49
+ `, { vec1, allowed_type: 'typeA' });
50
+ console.log("Results (type == $allowed_type):", res.rows);
51
+ }
52
+ catch (e) {
53
+ console.error("Error (type == $allowed_type):", e.message || e);
54
+ }
55
+ console.log("Creating table (with Validity)...");
56
+ // Recreate with Validity to match actual schema
57
+ await db.run(`{:create test_entity_v {id: String, created_at: Validity => type: String, metadata: Json, embedding: <F32; ${EMBEDDING_DIM}>}}`);
58
+ await db.run(`{::hnsw create test_entity_v:semantic {dim: ${EMBEDDING_DIM}, m: 16, dtype: F32, fields: [embedding], distance: Cosine, ef_construction: 200}}`);
59
+ const now = Date.now();
60
+ const dataV = [
61
+ ['id1', [now - 1000000, true], 'typeA', { status: 'active' }, vec1],
62
+ ['id2', [now, true], 'typeB', { status: 'inactive' }, vec2]
63
+ ];
64
+ await db.run(`
65
+ ?[id, created_at, type, metadata, embedding] <- $dataV
66
+ :put test_entity_v {id, created_at => type, metadata, embedding}
67
+ `, { dataV });
68
+ console.log("--- Test: Filter with is_in ---");
69
+ try {
70
+ const allowed_types = ['typeA', 'typeC'];
71
+ const res = await db.run(`
72
+ ?[id, type] := ~test_entity_v:semantic{id, type | query: vec($vec1), k: 2, ef: 100, filter: is_in(type, $allowed_types)}
73
+ `, { vec1, allowed_types });
74
+ console.log("Results (is_in(type, ...)):", res.rows);
75
+ }
76
+ catch (e) {
77
+ console.error("Error (is_in):", e.message || e);
78
+ }
79
+ }
80
+ catch (e) {
81
+ console.error("Global error:", e.message || e);
82
+ }
83
+ }
84
+ testFilterExpr().then(() => console.log("Done."));
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ async function main() {
5
+ console.log("🚀 Starting FTS (Full-Text Search) Test...");
6
+ const memory = new index_1.MemoryServer();
7
+ console.log("Waiting for schema...");
8
+ await memory.initPromise;
9
+ console.log("--- Schema ready ---");
10
+ console.log("1. Creating Test Data...");
11
+ // createEntity returns { id, name, type, status } or { error }
12
+ const e1 = await memory.createEntity({ name: "Berlin", type: "City", metadata: { description: "Berlin" } });
13
+ const e2 = await memory.createEntity({ name: "Munich", type: "City", metadata: { description: "Munich" } });
14
+ console.log("Entity 1 created:", e1.id || e1.error);
15
+ console.log("Entity 2 created:", e2.id || e2.error);
16
+ if (e1.error || e2.error) {
17
+ console.error("Failed to create entities");
18
+ return;
19
+ }
20
+ console.log("Adding Observations...");
21
+ await memory.addObservation({
22
+ entity_id: e1.id,
23
+ text: "Berlin is the capital of Germany. There are many museums.",
24
+ });
25
+ await memory.addObservation({
26
+ entity_id: e2.id,
27
+ text: "Munich is famous for Oktoberfest and technology development.",
28
+ });
29
+ await memory.addObservation({
30
+ entity_id: e1.id,
31
+ text: "The software is in beta stage and runs stably.",
32
+ });
33
+ console.log("Data created.");
34
+ console.log("\n2. Testing FTS Search...");
35
+ console.log("\n--- Test 1: Search for 'Capital' ---");
36
+ const res1 = await memory.advancedSearch({ query: "Capital", limit: 5 });
37
+ console.log(`Found: ${res1.length} results`);
38
+ res1.forEach((r) => console.log(` - [${r.source}] ${r.text?.substring(0, 50)}... (Score: ${r.score.toFixed(4)})`));
39
+ console.log("\n--- Test 2: Stemming Test ('developed' should find 'development') ---");
40
+ // "developed" stem -> "develop", "development" stem -> "develop"
41
+ // Cozo uses tantivy, check language support. Defaults to English?
42
+ const res2 = await memory.advancedSearch({ query: "developed", limit: 5 });
43
+ console.log(`Found: ${res2.length} results`);
44
+ res2.forEach((r) => console.log(` - [${r.source}] ${r.text?.substring(0, 50)}... (Score: ${r.score.toFixed(4)})`));
45
+ console.log("\n--- Test 3: Multiple Keywords ('Beta stable') ---");
46
+ const res3 = await memory.advancedSearch({ query: "Beta stable", limit: 5 });
47
+ console.log(`Found: ${res3.length} results`);
48
+ res3.forEach((r) => console.log(` - [${r.source}] ${r.text?.substring(0, 50)}... (Score: ${r.score.toFixed(4)})`));
49
+ console.log("\n--- Test 4: Stopwords Test ('the that') ---");
50
+ const res4 = await memory.advancedSearch({ query: "the that", limit: 5 });
51
+ console.log(`Found: ${res4.length} results (should be low or 0 if only stopwords)`);
52
+ }
53
+ main().catch((error) => {
54
+ console.log("❌ Test failed:", error);
55
+ if (error.display)
56
+ console.error(error.display);
57
+ });
58
+ console.log("\n✅ FTS Test completed.");
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cozo_node_1 = require("cozo-node");
7
+ const fs_1 = __importDefault(require("fs"));
8
+ async function testFunctions() {
9
+ const dbPath = "test-funcs.db";
10
+ if (fs_1.default.existsSync(dbPath)) {
11
+ try {
12
+ fs_1.default.unlinkSync(dbPath);
13
+ }
14
+ catch (e) { }
15
+ }
16
+ const db = new cozo_node_1.CozoDb("sqlite", dbPath);
17
+ try {
18
+ const res = await db.run(`::functions`);
19
+ console.log("Functions:", res.rows.map((r) => r[0]).sort());
20
+ }
21
+ catch (e) {
22
+ console.error("Error:", e.message || e);
23
+ }
24
+ }
25
+ testFunctions();
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const embedding_service_1 = require("./embedding-service");
4
+ async function checkGpu() {
5
+ console.log("Starting Embedding Test...");
6
+ try {
7
+ const service = new embedding_service_1.EmbeddingService();
8
+ // Embedding a dummy text to trigger initialization
9
+ await service.embed("Test Embedding");
10
+ console.log("Embedding successfully completed.");
11
+ }
12
+ catch (error) {
13
+ console.error("Error during embedding:", error);
14
+ }
15
+ }
16
+ checkGpu();
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ async function testNewGraphAlgorithms() {
5
+ const server = new index_1.MemoryServer('test_graph_algorithms');
6
+ console.log("--- Initialize test data ---");
7
+ // We build a network:
8
+ // A <-> B <-> C (B is bridge/betweenness)
9
+ // D -> E -> F -> D (Cycle for CC and HITS)
10
+ // G, H (Separate component)
11
+ const entities = [
12
+ { id: 'node_a', name: 'Node A', type: 'Test' },
13
+ { id: 'node_b', name: 'Node B (Bridge)', type: 'Test' },
14
+ { id: 'node_c', name: 'Node C', type: 'Test' },
15
+ { id: 'node_d', name: 'Node D', type: 'Test' },
16
+ { id: 'node_e', name: 'Node E', type: 'Test' },
17
+ { id: 'node_f', name: 'Node F', type: 'Test' },
18
+ { id: 'node_g', name: 'Node G', type: 'Test' },
19
+ { id: 'node_h', name: 'Node H', type: 'Test' }
20
+ ];
21
+ const relations = [
22
+ { from_id: 'node_a', to_id: 'node_b', action: 'create_relation', params: { from_id: 'node_a', to_id: 'node_b', relation_type: 'connects', strength: 0.8 } },
23
+ { from_id: 'node_b', to_id: 'node_c', action: 'create_relation', params: { from_id: 'node_b', to_id: 'node_c', relation_type: 'connects', strength: 0.9 } },
24
+ { from_id: 'node_d', to_id: 'node_e', action: 'create_relation', params: { from_id: 'node_d', to_id: 'node_e', relation_type: 'flow', strength: 1.0 } },
25
+ { from_id: 'node_e', to_id: 'node_f', action: 'create_relation', params: { from_id: 'node_e', to_id: 'node_f', relation_type: 'flow', strength: 1.0 } },
26
+ { from_id: 'node_f', to_id: 'node_d', action: 'create_relation', params: { from_id: 'node_f', to_id: 'node_d', relation_type: 'flow', strength: 1.0 } },
27
+ { from_id: 'node_g', to_id: 'node_h', action: 'create_relation', params: { from_id: 'node_g', to_id: 'node_h', relation_type: 'link', strength: 0.5 } }
28
+ ];
29
+ console.log("Creating entities...");
30
+ for (const ent of entities) {
31
+ await server.runTransaction({
32
+ operations: [{ action: 'create_entity', params: ent }]
33
+ });
34
+ }
35
+ console.log("Creating relationships...");
36
+ await server.runTransaction({
37
+ operations: relations.map(r => ({ action: 'create_relation', params: r.params }))
38
+ });
39
+ // Short pause for DB flush (SQLite is synchronous, but better safe than sorry)
40
+ await new Promise(resolve => setTimeout(resolve, 500));
41
+ // DEBUG: Check if data is present
42
+ console.log("Debug: Checking database content...");
43
+ const entitiesCount = await server.db.run(`?[count(e)] := *entity{id: e}`);
44
+ const relationsCount = await server.db.run(`?[count(f)] := *relationship{from_id: f, @ "NOW"}`);
45
+ console.log(`Debug: Entities in DB: ${entitiesCount.rows[0][0]}`);
46
+ console.log(`Debug: Relationships in DB: ${relationsCount.rows[0][0]}`);
47
+ if (relationsCount.rows[0][0] === 0) {
48
+ console.log("Trying alternative query without @ NOW...");
49
+ const relationsCountNoNow = await server.db.run(`?[count(f)] := *relationship{from_id: f}`);
50
+ console.log(`Debug: Relationships in DB (without NOW): ${relationsCountNoNow.rows[0][0]}`);
51
+ }
52
+ console.log("\n--- Test: Betweenness Centrality ---");
53
+ const betweenness = await server.recomputeBetweennessCentrality();
54
+ console.log("Betweenness Results:", JSON.stringify(betweenness.sort((a, b) => b.centrality - a.centrality), null, 2));
55
+ console.log("\n--- Test: Connected Components ---");
56
+ const components = await server.recomputeConnectedComponents();
57
+ console.log("Connected Components:", JSON.stringify(components, null, 2));
58
+ console.log("\n--- Test: Shortest Path (A -> C) ---");
59
+ const path = await server.computeShortestPath({ start_entity: 'node_a', end_entity: 'node_c' });
60
+ console.log("Shortest Path A->C:", JSON.stringify(path, null, 2));
61
+ console.log("\n--- Test: HITS (Hubs & Authorities) ---");
62
+ const hits = await server.recomputeHITS();
63
+ console.log("HITS Results:", JSON.stringify(hits, null, 2));
64
+ console.log("\n--- Test: PageRank ---");
65
+ const pagerank = await server.recomputePageRank();
66
+ console.log("PageRank Results (Top 5):", JSON.stringify(pagerank.sort((a, b) => b.pagerank - a.pagerank).slice(0, 5), null, 2));
67
+ console.log("\n--- Test: MCP Tool 'analyze_graph' ---");
68
+ // We simulate MCP calls via server methods, since FastMCP tools are encapsulated internally
69
+ console.log("Testing analyze_graph with action 'betweenness'...");
70
+ const resB = await server.recomputeBetweennessCentrality();
71
+ console.log("Result (Top 5):", JSON.stringify(resB.sort((a, b) => b.centrality - a.centrality).slice(0, 5), null, 2));
72
+ console.log("Testing analyze_graph with action 'shortest_path' (node_a to node_c)...");
73
+ const resP = await server.computeShortestPath({ start_entity: 'node_a', end_entity: 'node_c' });
74
+ console.log("Result:", JSON.stringify(resP, null, 2));
75
+ }
76
+ testNewGraphAlgorithms().catch(console.error);
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cozo_node_1 = require("cozo-node");
7
+ const hybrid_search_1 = require("./hybrid-search");
8
+ const embedding_service_1 = require("./embedding-service");
9
+ const fs_1 = __importDefault(require("fs"));
10
+ async function testGraphRagFilters() {
11
+ const dbPath = "test-graph-filters.db";
12
+ if (fs_1.default.existsSync(dbPath)) {
13
+ try {
14
+ fs_1.default.unlinkSync(dbPath);
15
+ }
16
+ catch (e) { }
17
+ }
18
+ const db = new cozo_node_1.CozoDb("sqlite", dbPath);
19
+ const embeddingService = new embedding_service_1.EmbeddingService();
20
+ const hybridSearch = new hybrid_search_1.HybridSearch(db, embeddingService);
21
+ try {
22
+ const EMBEDDING_DIM = 1024;
23
+ // Create schema
24
+ await db.run(`
25
+ {:create entity {id: String, created_at: Validity => name: String, type: String, embedding: <F32; ${EMBEDDING_DIM}>, metadata: Json}}
26
+ {:create relationship {from_id: String, to_id: String, relation_type: String => metadata: Json}}
27
+ {:create search_cache {query_hash: String => results: Json, options: Json, created_at: Int, embedding: <F32; ${EMBEDDING_DIM}>}}
28
+ {:create entity_rank {entity_id: String => pagerank: Float}}
29
+ `);
30
+ // Create HNSW index
31
+ await db.run(`::hnsw create entity:semantic {fields: [embedding], dim: ${EMBEDDING_DIM}, m: 16, ef_construction: 200, distance: Cosine}`);
32
+ // Test data (Office scenario)
33
+ // id1: Person (Developer), id2: Person (Manager), id3: Project (AI)
34
+ // id1 -> id3 (works_on), id2 -> id1 (manages)
35
+ const now = Date.now();
36
+ const vec1 = new Array(EMBEDDING_DIM).fill(0).map((_, i) => i === 0 ? 1 : 0);
37
+ const vec2 = new Array(EMBEDDING_DIM).fill(0).map((_, i) => i === 1 ? 1 : 0);
38
+ const vec3 = new Array(EMBEDDING_DIM).fill(0).map((_, i) => i === 2 ? 1 : 0);
39
+ console.log("Inserting entities...");
40
+ await db.run(`
41
+ ?[id, created_at, name, type, embedding, metadata] <- [
42
+ ['id1', 'ASSERT', 'Alice', 'Person', $v1, $m1],
43
+ ['id2', 'ASSERT', 'Bob', 'Person', $v2, $m2],
44
+ ['id3', 'ASSERT', 'Project X', 'Project', $v3, $m3]
45
+ ]
46
+ :put entity {id, created_at => name, type, embedding, metadata}
47
+ `, {
48
+ v1: vec1, v2: vec2, v3: vec3,
49
+ m1: { role: 'Developer' },
50
+ m2: { role: 'Manager' },
51
+ m3: { status: 'active' }
52
+ });
53
+ console.log("Entities inserted.");
54
+ console.log("Inserting relationships...");
55
+ await db.run(`
56
+ ?[from_id, to_id, relation_type, metadata] <- [
57
+ ['id2', 'id1', 'manages', {}],
58
+ ['id1', 'id3', 'works_on', {}]
59
+ ]
60
+ :put relationship {from_id, to_id, relation_type => metadata}
61
+ `);
62
+ console.log("Relationships inserted.");
63
+ console.log("\n--- Testing Graph-RAG: No Filters (Query 'Alice') ---");
64
+ // Should find Alice and via graph Bob (Manager) and Project X
65
+ let results = await hybridSearch.graphRag({ query: "Alice", limit: 5 });
66
+ console.log("Found:", results.map(r => `${r.id} (${r.name}, score: ${r.score.toFixed(4)})`));
67
+ console.log("\n--- Testing Graph-RAG: Filter Type 'Project' ---");
68
+ // Should only find Project X (as seed or via expansion, but here as seed)
69
+ // If we search for Alice but only allow Projects, Alice will not be found as seed.
70
+ // If Project X is similar enough to Alice, it will be found as seed.
71
+ results = await hybridSearch.graphRag({
72
+ query: "Project",
73
+ filters: { entityTypes: ['Project'] }
74
+ });
75
+ console.log("Found:", results.map(r => `${r.id} (${r.name})`));
76
+ console.log("\n--- Testing Graph-RAG: Filter Metadata role='Developer' ---");
77
+ // Alice should be seed, Bob and Project X via expansion
78
+ results = await hybridSearch.graphRag({
79
+ query: "Alice",
80
+ filters: { metadata: { role: 'Developer' } }
81
+ });
82
+ console.log("Found:", results.map(r => `${r.id} (${r.name})`));
83
+ }
84
+ catch (e) {
85
+ console.error("Test failed:", e.message || e);
86
+ }
87
+ }
88
+ testGraphRagFilters();
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
7
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
8
+ const path_1 = __importDefault(require("path"));
9
+ const serverPath = path_1.default.join(__dirname, "../dist/index.js");
10
+ async function runTest() {
11
+ const transport = new stdio_js_1.StdioClientTransport({
12
+ command: "node",
13
+ args: [serverPath],
14
+ env: { ...process.env, NODE_ENV: "development" }
15
+ });
16
+ const client = new index_js_1.Client({ name: "test-client", version: "1.0.0" }, { capabilities: {} });
17
+ try {
18
+ console.log("Connecting to MCP server for Graph-RAG Test...");
19
+ await client.connect(transport);
20
+ console.log("Connected!");
21
+ console.log("1. Create test data (Graph)...");
22
+ // Entities
23
+ const projectXRes = await client.callTool({
24
+ name: "mutate_memory",
25
+ arguments: {
26
+ action: "create_entity",
27
+ name: "Project-X",
28
+ type: "Project",
29
+ metadata: { priority: "high" }
30
+ }
31
+ });
32
+ const projectXId = JSON.parse(projectXRes.content[0].text).id;
33
+ const bobRes = await client.callTool({
34
+ name: "mutate_memory",
35
+ arguments: {
36
+ action: "create_entity",
37
+ name: "Bob",
38
+ type: "Person",
39
+ metadata: { role: "Manager" }
40
+ }
41
+ });
42
+ const bobId = JSON.parse(bobRes.content[0].text).id;
43
+ const aliceRes = await client.callTool({
44
+ name: "mutate_memory",
45
+ arguments: {
46
+ action: "create_entity",
47
+ name: "Alice",
48
+ type: "Person",
49
+ metadata: { role: "Developer" }
50
+ }
51
+ });
52
+ const aliceId = JSON.parse(aliceRes.content[0].text).id;
53
+ console.log(`IDs created: Project-X=${projectXId}, Bob=${bobId}, Alice=${aliceId}`);
54
+ // Relationships
55
+ await client.callTool({
56
+ name: "mutate_memory",
57
+ arguments: {
58
+ action: "create_relation",
59
+ from_id: aliceId,
60
+ to_id: projectXId,
61
+ relation_type: "works_on"
62
+ }
63
+ });
64
+ await client.callTool({
65
+ name: "mutate_memory",
66
+ arguments: {
67
+ action: "create_relation",
68
+ from_id: bobId,
69
+ to_id: projectXId,
70
+ relation_type: "manages"
71
+ }
72
+ });
73
+ // Observations
74
+ await client.callTool({
75
+ name: "mutate_memory",
76
+ arguments: {
77
+ action: "add_observation",
78
+ entity_id: aliceId,
79
+ text: "Alice works on the frontend architecture of Project-X."
80
+ }
81
+ });
82
+ await client.callTool({
83
+ name: "mutate_memory",
84
+ arguments: {
85
+ action: "add_observation",
86
+ entity_id: projectXId,
87
+ text: "Project-X is a new e-commerce platform."
88
+ }
89
+ });
90
+ console.log("2. Execute 'graph_rag' tool call...");
91
+ console.log("Query: 'Who works on Project-X?'");
92
+ const result = await client.callTool({
93
+ name: "query_memory",
94
+ arguments: {
95
+ action: "graph_rag",
96
+ query: "Project-X architecture",
97
+ limit: 5,
98
+ max_depth: 2
99
+ }
100
+ });
101
+ console.log("\n--- Graph-RAG Result ---");
102
+ console.log(JSON.stringify(result, null, 2));
103
+ if (result && result.content) {
104
+ const content = JSON.parse(result.content[0].text);
105
+ console.log(`\nFound entries: ${content.length}`);
106
+ const names = content.map((r) => r.name);
107
+ console.log("Found entities:", [...new Set(names)]);
108
+ if (names.some((n) => n.includes("Alice") || n === "Alice") && names.includes("Project-X")) {
109
+ console.log("\n✅ Test SUCCESSFUL: Alice and Project-X were found via graph expansion.");
110
+ }
111
+ else {
112
+ console.log("\n❌ Test FAILED: Expected entities not fully in result.");
113
+ console.log("Sought entities: Alice, Project-X");
114
+ }
115
+ }
116
+ }
117
+ catch (error) {
118
+ console.error("Error testing:", error);
119
+ }
120
+ finally {
121
+ process.exit(0);
122
+ }
123
+ }
124
+ runTest();