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.
- package/LICENSE +201 -0
- package/README.md +533 -0
- package/dist/api_bridge.js +266 -0
- package/dist/benchmark-gpu-cpu.js +188 -0
- package/dist/benchmark-heavy.js +230 -0
- package/dist/benchmark.js +160 -0
- package/dist/clear-cache.js +29 -0
- package/dist/db-service.js +228 -0
- package/dist/download-model.js +48 -0
- package/dist/embedding-service.js +249 -0
- package/dist/full-system-test.js +45 -0
- package/dist/hybrid-search.js +337 -0
- package/dist/index.js +3106 -0
- package/dist/inference-engine.js +348 -0
- package/dist/memory-service.js +215 -0
- package/dist/test-advanced-filters.js +64 -0
- package/dist/test-advanced-search.js +82 -0
- package/dist/test-advanced-time.js +47 -0
- package/dist/test-embedding.js +22 -0
- package/dist/test-filter-expr.js +84 -0
- package/dist/test-fts.js +58 -0
- package/dist/test-functions.js +25 -0
- package/dist/test-gpu-check.js +16 -0
- package/dist/test-graph-algs-final.js +76 -0
- package/dist/test-graph-filters.js +88 -0
- package/dist/test-graph-rag.js +124 -0
- package/dist/test-graph-walking.js +138 -0
- package/dist/test-index.js +35 -0
- package/dist/test-int-filter.js +48 -0
- package/dist/test-integration.js +69 -0
- package/dist/test-lower.js +35 -0
- package/dist/test-lsh.js +67 -0
- package/dist/test-mcp-tool.js +40 -0
- package/dist/test-pagerank.js +31 -0
- package/dist/test-semantic-walk.js +145 -0
- package/dist/test-time-filter.js +66 -0
- package/dist/test-time-functions.js +38 -0
- package/dist/test-triggers.js +60 -0
- package/dist/test-ts-ort.js +48 -0
- package/dist/test-validity-access.js +35 -0
- package/dist/test-validity-body.js +42 -0
- package/dist/test-validity-decomp.js +37 -0
- package/dist/test-validity-extraction.js +45 -0
- package/dist/test-validity-json.js +35 -0
- package/dist/test-validity.js +38 -0
- package/dist/types.js +3 -0
- package/dist/verify-gpu.js +30 -0
- package/dist/verify_transaction_tool.js +46 -0
- package/package.json +75 -0
|
@@ -0,0 +1,138 @@
|
|
|
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-Walking Test...");
|
|
19
|
+
await client.connect(transport);
|
|
20
|
+
console.log("Connected!");
|
|
21
|
+
console.log("1. Preparing test data...");
|
|
22
|
+
// Cleanup
|
|
23
|
+
await client.callTool({
|
|
24
|
+
name: "manage_system",
|
|
25
|
+
arguments: { action: "clear_memory", confirm: true }
|
|
26
|
+
});
|
|
27
|
+
// Create a semantic network
|
|
28
|
+
// Topic: Artificial Intelligence and its applications
|
|
29
|
+
const entities = [
|
|
30
|
+
{ name: "AI Research", type: "Field", text: "Research on artificial intelligence and machine learning." },
|
|
31
|
+
{ name: "Neural Networks", type: "Technology", text: "Neural networks are the basis for modern deep learning." },
|
|
32
|
+
{ name: "Transformer Architecture", type: "Architecture", text: "Transformers are specialized neural networks for language processing." },
|
|
33
|
+
{ name: "Large Language Models", type: "Application", text: "LLMs use transformers to generate human-like text." },
|
|
34
|
+
{ name: "GPT-4", type: "Model", text: "GPT-4 is a powerful Large Language Model from OpenAI." },
|
|
35
|
+
{ name: "Ethics in AI", type: "Topic", text: "Discussion about responsible development of AI systems." },
|
|
36
|
+
{ name: "Quantum Computing", type: "Field", text: "Quantum computers use quantum mechanics for calculations." } // Slightly further away
|
|
37
|
+
];
|
|
38
|
+
const entityIds = {};
|
|
39
|
+
console.log("Creating entities via 'add_observation'...");
|
|
40
|
+
for (const ent of entities) {
|
|
41
|
+
const res = await client.callTool({
|
|
42
|
+
name: "mutate_memory",
|
|
43
|
+
arguments: {
|
|
44
|
+
action: "add_observation",
|
|
45
|
+
entity_name: ent.name,
|
|
46
|
+
entity_type: ent.type,
|
|
47
|
+
text: ent.text,
|
|
48
|
+
metadata: { description: ent.text }
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
const content = res.content[0].text;
|
|
52
|
+
const parsed = JSON.parse(content);
|
|
53
|
+
if (parsed.error) {
|
|
54
|
+
console.error(`Error creating ${ent.name}:`, parsed.error);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const id = parsed.entity_id || parsed.id;
|
|
58
|
+
if (!id) {
|
|
59
|
+
console.error(`No ID received for ${ent.name}. Response:`, JSON.stringify(parsed, null, 2));
|
|
60
|
+
}
|
|
61
|
+
entityIds[ent.name] = id;
|
|
62
|
+
}
|
|
63
|
+
console.log("Created entities:", Object.keys(entityIds));
|
|
64
|
+
// Create relationships (graph structure)
|
|
65
|
+
const relations = [
|
|
66
|
+
["AI Research", "Neural Networks", "develops"],
|
|
67
|
+
["Neural Networks", "Transformer Architecture", "enables"],
|
|
68
|
+
["Transformer Architecture", "Large Language Models", "is basis of"],
|
|
69
|
+
["Large Language Models", "GPT-4", "includes"],
|
|
70
|
+
["GPT-4", "Ethics in AI", "discussed in"],
|
|
71
|
+
["AI Research", "Ethics in AI", "includes"],
|
|
72
|
+
["AI Research", "Quantum Computing", "might use"]
|
|
73
|
+
];
|
|
74
|
+
for (const [from, to, type] of relations) {
|
|
75
|
+
const fromId = entityIds[from];
|
|
76
|
+
const toId = entityIds[to];
|
|
77
|
+
if (!fromId || !toId) {
|
|
78
|
+
console.error(`Error: ID for ${from} or ${to} not found!`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
await client.callTool({
|
|
82
|
+
name: "mutate_memory",
|
|
83
|
+
arguments: {
|
|
84
|
+
action: "create_relation",
|
|
85
|
+
from_id: fromId,
|
|
86
|
+
to_id: toId,
|
|
87
|
+
relation_type: type
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
console.log("Relationships created.");
|
|
92
|
+
console.log("\n2. Test: Graph Walking (Vector Seed)");
|
|
93
|
+
console.log("Searching for: 'How do modern language models work?'");
|
|
94
|
+
const walkRes1 = await client.callTool({
|
|
95
|
+
name: "query_memory",
|
|
96
|
+
arguments: {
|
|
97
|
+
action: "graph_walking",
|
|
98
|
+
query: "How do modern language models work?",
|
|
99
|
+
max_depth: 3,
|
|
100
|
+
limit: 5
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
console.log("Result Walk 1:", JSON.stringify(JSON.parse(walkRes1.content[0].text), null, 2));
|
|
104
|
+
console.log("\n3. Test: Graph Walking (Start Entity)");
|
|
105
|
+
console.log(`Start at 'GPT-4' and search for ethics`);
|
|
106
|
+
const walkRes2 = await client.callTool({
|
|
107
|
+
name: "query_memory",
|
|
108
|
+
arguments: {
|
|
109
|
+
action: "graph_walking",
|
|
110
|
+
query: "Ethical concerns in AI",
|
|
111
|
+
start_entity_id: entityIds["GPT-4"],
|
|
112
|
+
max_depth: 2,
|
|
113
|
+
limit: 3
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
console.log("Result Walk 2:", JSON.stringify(JSON.parse(walkRes2.content[0].text), null, 2));
|
|
117
|
+
console.log("\n4. Test: Graph Walking (Distance Check)");
|
|
118
|
+
console.log("Search for 'quantum computer' starting from 'GPT-4' (should have little relevance or be too far away)");
|
|
119
|
+
const walkRes3 = await client.callTool({
|
|
120
|
+
name: "query_memory",
|
|
121
|
+
arguments: {
|
|
122
|
+
action: "graph_walking",
|
|
123
|
+
query: "Quantum computing hardware",
|
|
124
|
+
start_entity_id: entityIds["GPT-4"],
|
|
125
|
+
max_depth: 2,
|
|
126
|
+
limit: 5
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
console.log("Result Walk 3:", JSON.stringify(JSON.parse(walkRes3.content[0].text), null, 2));
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error("Test failed:", error);
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
runTest();
|
|
@@ -0,0 +1,35 @@
|
|
|
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 testArrayIndex() {
|
|
9
|
+
const dbPath = "test-index.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
|
+
await db.run(`{:create test_v {id: String, v: Validity => t: String}}`);
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const data = [['id1', [now - 1000, true], 'typeA']];
|
|
21
|
+
await db.run(`?[id, v, t] <- $data :put test_v {id, v => t}`, { data });
|
|
22
|
+
console.log("--- Test v[0] ---");
|
|
23
|
+
try {
|
|
24
|
+
const res = await db.run(`?[id, start] := *test_v{id, v}, start = v[0]`);
|
|
25
|
+
console.log("v[0] results:", res.rows);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error("v[0] error:", e.message || e);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.error("Global error:", e.message || e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
testArrayIndex();
|
|
@@ -0,0 +1,48 @@
|
|
|
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 testIntFilter() {
|
|
9
|
+
const dbPath = "test-int.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 = 4;
|
|
18
|
+
try {
|
|
19
|
+
console.log("Creating table with Int created_at...");
|
|
20
|
+
await db.run(`{:create test_int {id: String, created_at: Int => type: String, embedding: <F32; ${EMBEDDING_DIM}>}}`);
|
|
21
|
+
await db.run(`{::hnsw create test_int:semantic {dim: ${EMBEDDING_DIM}, m: 16, dtype: F32, fields: [embedding], distance: Cosine, ef_construction: 200}}`);
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
const vec = [0.1, 0.2, 0.3, 0.4];
|
|
24
|
+
const data = [
|
|
25
|
+
['old', now - 10000000, 'old_type', vec],
|
|
26
|
+
['new', now, 'new_type', vec]
|
|
27
|
+
];
|
|
28
|
+
await db.run(`
|
|
29
|
+
?[id, created_at, type, embedding] <- $data
|
|
30
|
+
:put test_int {id, created_at => type, embedding}
|
|
31
|
+
`, { data });
|
|
32
|
+
console.log("--- Test: Int filter in HNSW ---");
|
|
33
|
+
try {
|
|
34
|
+
const min_ts = now - 5000000;
|
|
35
|
+
const res = await db.run(`
|
|
36
|
+
?[id, ca] := ~test_int:semantic{id, created_at | query: vec($vec), k: 10, ef: 100, filter: created_at > $min_ts}, ca = created_at
|
|
37
|
+
`, { vec, min_ts });
|
|
38
|
+
console.log("Results HNSW filter:", res.rows);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
console.error("Error HNSW filter:", e.message || e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
console.error("Global error:", e.message || e);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
testIntFilter();
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("./index");
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
async function testIntegration() {
|
|
6
|
+
console.log("Starting Integration Test...");
|
|
7
|
+
const memory = new index_1.MemoryServer();
|
|
8
|
+
try {
|
|
9
|
+
// 1. Initialize
|
|
10
|
+
console.log("Initializing MemoryServer...");
|
|
11
|
+
await memory.initPromise;
|
|
12
|
+
// 2. Create Entity
|
|
13
|
+
console.log("Creating Entity...");
|
|
14
|
+
const entityName = `Test-Entity-${(0, uuid_1.v4)().substring(0, 8)}`;
|
|
15
|
+
const createResult = await memory.createEntity({
|
|
16
|
+
name: entityName,
|
|
17
|
+
type: "test_project",
|
|
18
|
+
metadata: { status: "active" }
|
|
19
|
+
});
|
|
20
|
+
console.log("Create Entity Result:", createResult);
|
|
21
|
+
const entityId = createResult.id;
|
|
22
|
+
console.log(`Entity ID: ${entityId}`);
|
|
23
|
+
if (!entityId)
|
|
24
|
+
throw new Error("No Entity ID returned");
|
|
25
|
+
// 3. Add Observation
|
|
26
|
+
// Assuming addObservation is public like createEntity
|
|
27
|
+
console.log("Adding Observation...");
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
const obsResult = await memory.addObservation({
|
|
30
|
+
entity_id: entityId,
|
|
31
|
+
text: "This is a test observation to verify embedding generation and storage.",
|
|
32
|
+
metadata: { priority: "high" }
|
|
33
|
+
});
|
|
34
|
+
console.log("Add Observation Result:", obsResult);
|
|
35
|
+
// 4. Search (Tests Embedding)
|
|
36
|
+
console.log("Searching (Testing Embeddings)...");
|
|
37
|
+
// Search is likely exposed via hybridSearch or a method on memory
|
|
38
|
+
// Checking index.ts, it has hybridSearch property.
|
|
39
|
+
// But maybe there is a search method on MemoryServer too?
|
|
40
|
+
// Let's assume we can use hybridSearch directly or look for a wrapper.
|
|
41
|
+
// Reading index.ts revealed createEntity. Let's check for search wrapper.
|
|
42
|
+
// If not found, use memory.hybridSearch.search(...)
|
|
43
|
+
// I'll try memory.hybridSearch.search first if no wrapper is obvious.
|
|
44
|
+
// But wait, the tool call was "query_memory" action "search".
|
|
45
|
+
// That likely calls memory.hybridSearch.search.
|
|
46
|
+
const searchResult = await memory.hybridSearch.search({
|
|
47
|
+
query: "verify embedding generation",
|
|
48
|
+
limit: 5,
|
|
49
|
+
includeEntities: true
|
|
50
|
+
});
|
|
51
|
+
console.log("Search Result:", JSON.stringify(searchResult).substring(0, 200) + "...");
|
|
52
|
+
// 5. Snapshot (Tests Optimization)
|
|
53
|
+
// Snapshot logic is in manage_system tool.
|
|
54
|
+
// I need to check if there is a snapshot method.
|
|
55
|
+
// I saw snapshot code in the tool handler in index.ts previously.
|
|
56
|
+
// It might not be a separate public method on MemoryServer.
|
|
57
|
+
// If so, I might need to extract it or test it via a different way.
|
|
58
|
+
// But wait, I can probably access the database directly to test the count logic if needed.
|
|
59
|
+
// Or I can just skip snapshot test if it's inside the tool handler closure.
|
|
60
|
+
// However, I want to verify the fix.
|
|
61
|
+
// Let's look for a public snapshot method. If not, I'll simulate the logic.
|
|
62
|
+
console.log("Integration Test Completed Successfully!");
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error("Integration Test Failed:", error);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
testIntegration();
|
|
@@ -0,0 +1,35 @@
|
|
|
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 testValidityLower() {
|
|
9
|
+
const dbPath = "test-lower.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
|
+
await db.run(`{:create test_v {id: String, v: Validity => t: String}}`);
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const data = [['id1', [now - 1000, true], 'typeA']];
|
|
21
|
+
await db.run(`?[id, v, t] <- $data :put test_v {id, v => t}`, { data });
|
|
22
|
+
console.log("--- Test lower(v) without @ ---");
|
|
23
|
+
try {
|
|
24
|
+
const res = await db.run(`?[id, start] := *test_v{id, v}, start = lower(v)`);
|
|
25
|
+
console.log("lower(v) results:", res.rows);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error("lower(v) error:", e.message || e);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.error("Global error:", e.message || e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
testValidityLower();
|
package/dist/test-lsh.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
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("./index.js");
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const TEST_DB_PATH = path_1.default.join(process.cwd(), "lsh_test_db");
|
|
10
|
+
async function runLSHTest() {
|
|
11
|
+
console.log("🚀 Starting LSH (MinHash) Deduplication Test...");
|
|
12
|
+
// Cleanup
|
|
13
|
+
if (fs_1.default.existsSync(TEST_DB_PATH + ".db")) {
|
|
14
|
+
fs_1.default.unlinkSync(TEST_DB_PATH + ".db");
|
|
15
|
+
}
|
|
16
|
+
const server = new index_js_1.MemoryServer(TEST_DB_PATH);
|
|
17
|
+
try {
|
|
18
|
+
await server.initPromise; // Ensure schema is ready
|
|
19
|
+
console.log("1. Creating Test Entity...");
|
|
20
|
+
const e1 = await server.createEntity({ name: "LSH Test Project", type: "Test", metadata: { version: 1 } });
|
|
21
|
+
console.log("2. Ingesting first text...");
|
|
22
|
+
await server.ingestFile({
|
|
23
|
+
entity_id: e1.id,
|
|
24
|
+
format: "markdown",
|
|
25
|
+
content: "This is a very long text about the development of artificial intelligence in the modern world."
|
|
26
|
+
});
|
|
27
|
+
console.log("3. Testing Near-Duplicate (slightly modified)...");
|
|
28
|
+
// Just one word changed or slightly modified
|
|
29
|
+
const res2 = await server.ingestFile({
|
|
30
|
+
entity_id: e1.id,
|
|
31
|
+
format: "markdown",
|
|
32
|
+
content: "This is a very long text about the development of AI in the modern world.",
|
|
33
|
+
deduplicate: true
|
|
34
|
+
});
|
|
35
|
+
console.log(`Result 2 (Near-Duplicate): ${res2.observations_added} added, ${res2.observations_skipped_duplicates} skipped`);
|
|
36
|
+
if (res2.observations_skipped_duplicates > 0) {
|
|
37
|
+
console.log("✅ LSH successfully detected the near-duplicate.");
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log("❌ LSH did NOT detect the near-duplicate.");
|
|
41
|
+
}
|
|
42
|
+
console.log("\n4. Testing JSON Update (v0.7 Feature)...");
|
|
43
|
+
const updateRes = await server.updateEntity({
|
|
44
|
+
id: e1.id,
|
|
45
|
+
metadata: { new_field: "updated", version: 2 }
|
|
46
|
+
});
|
|
47
|
+
console.log("Update Status:", updateRes.status);
|
|
48
|
+
const verifyRes = await server.db.run('?[meta] := *entity{id: $id, metadata: meta, @ "NOW"}', { id: e1.id });
|
|
49
|
+
console.log("Verified Metadata:", JSON.stringify(verifyRes.rows[0][0]));
|
|
50
|
+
if (verifyRes.rows[0][0].version === 2 && verifyRes.rows[0][0].new_field === "updated") {
|
|
51
|
+
console.log("✅ JSON Merge (++) successful.");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log("❌ JSON Merge (++) failed.");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error("❌ Test failed:", error);
|
|
59
|
+
if (error.display)
|
|
60
|
+
console.error(error.display);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
console.log("\n✅ LSH & JSON Test completed.");
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
runLSHTest();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
4
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
5
|
+
async function main() {
|
|
6
|
+
console.log("Connecting to MCP server...");
|
|
7
|
+
const client = new index_js_1.Client({
|
|
8
|
+
name: "mcp-test-client",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
}, {
|
|
11
|
+
capabilities: {},
|
|
12
|
+
});
|
|
13
|
+
const transport = new stdio_js_1.StdioClientTransport({
|
|
14
|
+
command: "npx",
|
|
15
|
+
args: ["ts-node", "src/index.ts"],
|
|
16
|
+
});
|
|
17
|
+
await client.connect(transport);
|
|
18
|
+
console.log("Connected!");
|
|
19
|
+
console.log("Executing 'add_observation' Tool-Call...");
|
|
20
|
+
await client.callTool({
|
|
21
|
+
name: "add_observation",
|
|
22
|
+
arguments: {
|
|
23
|
+
text: "The sky is blue.",
|
|
24
|
+
entity_id: "nature_facts",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
console.log("Executing 'advancedSearch' Tool-Call...");
|
|
28
|
+
const result = await client.callTool({
|
|
29
|
+
name: "advancedSearch",
|
|
30
|
+
arguments: {
|
|
31
|
+
query: "blue sky",
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
console.log("Result from Tool:");
|
|
35
|
+
console.log(JSON.stringify(result, null, 2));
|
|
36
|
+
await client.close();
|
|
37
|
+
}
|
|
38
|
+
main().catch((error) => {
|
|
39
|
+
console.log("Error during test:", error);
|
|
40
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("./index");
|
|
4
|
+
async function testPageRank() {
|
|
5
|
+
const server = new index_1.MemoryServer('test_pagerank');
|
|
6
|
+
console.log("--- Creating Entities ---");
|
|
7
|
+
const idA = "entity_a";
|
|
8
|
+
const idB = "entity_b";
|
|
9
|
+
const idC = "entity_c";
|
|
10
|
+
const idD = "entity_d";
|
|
11
|
+
await server.runTransaction({
|
|
12
|
+
operations: [
|
|
13
|
+
{ action: 'create_entity', params: { id: idA, name: 'Zentraler Knoten A', type: 'Node' } },
|
|
14
|
+
{ action: 'create_entity', params: { id: idB, name: 'Knoten B', type: 'Node' } },
|
|
15
|
+
{ action: 'create_entity', params: { id: idC, name: 'Knoten C', type: 'Node' } },
|
|
16
|
+
{ action: 'create_entity', params: { id: idD, name: 'Isolierter Knoten D', type: 'Node' } },
|
|
17
|
+
{ action: 'create_relation', params: { from_id: idB, to_id: idA, relation_type: 'points_to', strength: 1.0 } },
|
|
18
|
+
{ action: 'create_relation', params: { from_id: idC, to_id: idA, relation_type: 'points_to', strength: 1.0 } }
|
|
19
|
+
]
|
|
20
|
+
});
|
|
21
|
+
console.log("--- Calculating PageRank ---");
|
|
22
|
+
const rankRes = await server.recomputePageRank();
|
|
23
|
+
console.log("Ranks:", JSON.stringify(rankRes, null, 2));
|
|
24
|
+
console.log("--- Searching for 'Node' (A should be boosted by PageRank) ---");
|
|
25
|
+
const searchRes = await server.advancedSearch({ query: 'Knoten', limit: 5 });
|
|
26
|
+
console.log("Suchergebnisse:");
|
|
27
|
+
searchRes.forEach((r, i) => {
|
|
28
|
+
console.log(`${i + 1}. ${r.name} - Score: ${r.score.toFixed(4)}`);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
testPageRank().catch(console.error);
|
|
@@ -0,0 +1,145 @@
|
|
|
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 Semantic Walk Test...");
|
|
19
|
+
await client.connect(transport);
|
|
20
|
+
console.log("Connected!");
|
|
21
|
+
console.log("\n1. Preparing test data...");
|
|
22
|
+
// Cleanup
|
|
23
|
+
await client.callTool({
|
|
24
|
+
name: "manage_system",
|
|
25
|
+
arguments: { action: "clear_memory", confirm: true }
|
|
26
|
+
});
|
|
27
|
+
// Create entities
|
|
28
|
+
// We want to test paths:
|
|
29
|
+
// A (Start) -> B (Explicit)
|
|
30
|
+
// A (Start) ~ C (Semantic)
|
|
31
|
+
// B -> D (Explicit) => A -> B -> D (Explicit Path Depth 2)
|
|
32
|
+
// B ~ E (Semantic) => A -> B ~ E (Mixed Path)
|
|
33
|
+
const entities = [
|
|
34
|
+
{ name: "Apple", type: "Fruit", text: "A red apple, a popular fruit." }, // Start
|
|
35
|
+
{ name: "Fruit Tree", type: "Plant", text: "A tree where fruits grow." }, // Connected to Apple
|
|
36
|
+
{ name: "Pear", type: "Fruit", text: "A green pear, similar to an apple." }, // Semantically similar to Apple
|
|
37
|
+
{ name: "Garden", type: "Location", text: "A place where plants grow." }, // Connected to Fruit Tree
|
|
38
|
+
{ name: "Banana", type: "Fruit", text: "A yellow curved fruit." }, // Semantically similar to Pear (and Apple?)
|
|
39
|
+
{ name: "Pear Tree", type: "Plant", text: "A tree where pears grow." } // Mixed Path Test
|
|
40
|
+
];
|
|
41
|
+
const entityIds = {};
|
|
42
|
+
console.log("Creating entities...");
|
|
43
|
+
for (const ent of entities) {
|
|
44
|
+
const res = await client.callTool({
|
|
45
|
+
name: "mutate_memory",
|
|
46
|
+
arguments: {
|
|
47
|
+
action: "add_observation",
|
|
48
|
+
entity_name: ent.name,
|
|
49
|
+
entity_type: ent.type,
|
|
50
|
+
text: ent.text
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const content = JSON.parse(res.content[0].text);
|
|
54
|
+
const id = content.entity_id || content.id;
|
|
55
|
+
entityIds[ent.name] = id;
|
|
56
|
+
console.log(` - ${ent.name}: ${id}`);
|
|
57
|
+
}
|
|
58
|
+
// Creating relationships
|
|
59
|
+
console.log("\nCreating relationships...");
|
|
60
|
+
// Apple -> grows on -> Fruit Tree (Explicit)
|
|
61
|
+
await client.callTool({
|
|
62
|
+
name: "mutate_memory",
|
|
63
|
+
arguments: {
|
|
64
|
+
action: "create_relation",
|
|
65
|
+
from_id: entityIds["Apple"],
|
|
66
|
+
to_id: entityIds["Fruit Tree"],
|
|
67
|
+
relation_type: "grows_on",
|
|
68
|
+
strength: 1.0
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// Fruit Tree -> located in -> Garden (Explicit)
|
|
72
|
+
await client.callTool({
|
|
73
|
+
name: "mutate_memory",
|
|
74
|
+
arguments: {
|
|
75
|
+
action: "create_relation",
|
|
76
|
+
from_id: entityIds["Fruit Tree"],
|
|
77
|
+
to_id: entityIds["Garden"],
|
|
78
|
+
relation_type: "located_in",
|
|
79
|
+
strength: 1.0
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
// Pear -> grows on -> Pear Tree (Explicit)
|
|
83
|
+
await client.callTool({
|
|
84
|
+
name: "mutate_memory",
|
|
85
|
+
arguments: {
|
|
86
|
+
action: "create_relation",
|
|
87
|
+
from_id: entityIds["Pear"],
|
|
88
|
+
to_id: entityIds["Pear Tree"],
|
|
89
|
+
relation_type: "grows_on",
|
|
90
|
+
strength: 1.0
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
console.log("Data prepared.");
|
|
94
|
+
// Test 1: Semantic Walk from "Apple"
|
|
95
|
+
console.log("\n2. Starting Semantic Graph Walk (Start: Apple)...");
|
|
96
|
+
const walkRes = await client.callTool({
|
|
97
|
+
name: "analyze_graph",
|
|
98
|
+
arguments: {
|
|
99
|
+
action: "semantic_walk",
|
|
100
|
+
start_entity: entityIds["Apple"],
|
|
101
|
+
max_depth: 3,
|
|
102
|
+
min_similarity: 0.6 // Slightly lower for the test
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const result = JSON.parse(walkRes.content[0].text);
|
|
106
|
+
console.log(`\nFound entities: ${result.found_entities}`);
|
|
107
|
+
console.log("\nResults:");
|
|
108
|
+
const foundNames = new Set();
|
|
109
|
+
for (const r of result.results) {
|
|
110
|
+
console.log(`- ${r.entity_name} (${r.entity_type})`);
|
|
111
|
+
console.log(` Depth: ${r.distance}, Score: ${r.path_score.toFixed(3)}, Type: ${r.path_type}`);
|
|
112
|
+
foundNames.add(r.entity_name);
|
|
113
|
+
}
|
|
114
|
+
// Validation
|
|
115
|
+
console.log("\nValidation:");
|
|
116
|
+
// 1. Fruit Tree should be found (Explicit, Depth 1)
|
|
117
|
+
if (foundNames.has("Fruit Tree"))
|
|
118
|
+
console.log("✅ Fruit Tree found (Explicit)");
|
|
119
|
+
else
|
|
120
|
+
console.error("❌ Fruit Tree NOT found");
|
|
121
|
+
// 2. Pear should be found (Semantic, Depth 1)
|
|
122
|
+
if (foundNames.has("Pear"))
|
|
123
|
+
console.log("✅ Pear found (Semantic)");
|
|
124
|
+
else
|
|
125
|
+
console.error("❌ Pear NOT found (Maybe embedding problem?)");
|
|
126
|
+
// 3. Garden should be found (Explicit Path: Apple -> Fruit Tree -> Garden, Depth 2)
|
|
127
|
+
if (foundNames.has("Garden"))
|
|
128
|
+
console.log("✅ Garden found (Transitive Explicit)");
|
|
129
|
+
else
|
|
130
|
+
console.error("❌ Garden NOT found");
|
|
131
|
+
// 4. Banana could be found (Semantic or Mixed)
|
|
132
|
+
if (foundNames.has("Banana"))
|
|
133
|
+
console.log("✅ Banana found");
|
|
134
|
+
else
|
|
135
|
+
console.log("ℹ️ Banana not found (OK, depends on Similarity)");
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error("Test failed:", error);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
await transport.close();
|
|
142
|
+
process.exit(0);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
runTest();
|