cozo-memory 1.2.0 → 1.2.2
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/dist/emotional-salience.js +295 -0
- package/dist/index.js +726 -9
- package/dist/memory-activation.js +64 -30
- package/dist/memory-service.js +68 -0
- package/dist/pre-storage-reasoning.js +351 -0
- package/dist/temporal-conflict-resolution.js +10 -6
- package/dist/test-activation-mcp.js +118 -0
- package/dist/test-advanced-search-mcp.js +204 -0
- package/dist/test-conflicts-mcp.js +173 -0
- package/dist/test-emotional-salience.js +177 -0
- package/dist/test-hierarchical-mcp.js +135 -0
- package/dist/test-logical-edges-mcp.js +215 -0
- package/dist/test-metadata-check.js +69 -0
- package/dist/test-metadata-update.js +92 -0
- package/dist/test-pre-storage-reasoning.js +149 -0
- package/dist/test-salience-mcp.js +94 -0
- package/dist/test-spreading-mcp.js +155 -0
- package/dist/test-suggest-connections-mcp.js +172 -0
- package/dist/test-zettelkasten-evolution.js +255 -0
- package/dist/test-zettelkasten-fixed.js +74 -0
- package/dist/test-zettelkasten-live.js +117 -0
- package/dist/test-zettelkasten-mcp.js +96 -0
- package/dist/zettelkasten-evolution.js +342 -0
- package/package.json +1 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cozo_node_1 = require("cozo-node");
|
|
4
|
+
const zettelkasten_evolution_1 = require("./zettelkasten-evolution");
|
|
5
|
+
const embedding_service_1 = require("./embedding-service");
|
|
6
|
+
async function testZettelkastenEvolution() {
|
|
7
|
+
console.log('=== Zettelkasten Memory Evolution Test ===\n');
|
|
8
|
+
const db = new cozo_node_1.CozoDb();
|
|
9
|
+
const embeddingService = new embedding_service_1.EmbeddingService();
|
|
10
|
+
const zettelService = new zettelkasten_evolution_1.ZettelkastenEvolutionService(db, embeddingService, {
|
|
11
|
+
enableEvolution: true,
|
|
12
|
+
similarityThreshold: 0.7,
|
|
13
|
+
maxRelatedNotes: 5,
|
|
14
|
+
minKeywordFrequency: 1, // Lower for testing
|
|
15
|
+
autoExtractKeywords: true,
|
|
16
|
+
autoBidirectionalLinks: true,
|
|
17
|
+
enrichmentDepth: 'shallow'
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
// Initialize database schema
|
|
21
|
+
await db.run(`
|
|
22
|
+
:create entity {
|
|
23
|
+
id: String,
|
|
24
|
+
=>
|
|
25
|
+
name: String,
|
|
26
|
+
type: String,
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
await db.run(`
|
|
30
|
+
:create observation {
|
|
31
|
+
id: String,
|
|
32
|
+
created_at: Validity,
|
|
33
|
+
=>
|
|
34
|
+
entity_id: String,
|
|
35
|
+
session_id: String?,
|
|
36
|
+
task_id: String?,
|
|
37
|
+
text: String,
|
|
38
|
+
embedding: <F32; 1024>,
|
|
39
|
+
metadata: Json?,
|
|
40
|
+
}
|
|
41
|
+
`);
|
|
42
|
+
await db.run(`
|
|
43
|
+
:create relationship {
|
|
44
|
+
from_id: String,
|
|
45
|
+
to_id: String,
|
|
46
|
+
relation_type: String,
|
|
47
|
+
=>
|
|
48
|
+
strength: Float,
|
|
49
|
+
metadata: Json?,
|
|
50
|
+
}
|
|
51
|
+
`);
|
|
52
|
+
// Create HNSW index for semantic search
|
|
53
|
+
await db.run(`
|
|
54
|
+
::hnsw create observation:semantic {
|
|
55
|
+
dim: 1024,
|
|
56
|
+
m: 50,
|
|
57
|
+
dtype: F32,
|
|
58
|
+
fields: [embedding],
|
|
59
|
+
distance: Cosine,
|
|
60
|
+
ef_construction: 200
|
|
61
|
+
}
|
|
62
|
+
`);
|
|
63
|
+
console.log('✓ Database initialized\n');
|
|
64
|
+
// Test 1: Create test entity
|
|
65
|
+
console.log('Test 1: Creating test entity...');
|
|
66
|
+
await db.run(`
|
|
67
|
+
?[id, name, type] <- [['test-entity', 'Knowledge Base', 'System']]
|
|
68
|
+
:put entity {id, name, type}
|
|
69
|
+
`);
|
|
70
|
+
console.log('✓ Entity created\n');
|
|
71
|
+
// Test 2: Create initial observations
|
|
72
|
+
console.log('Test 2: Creating initial observations...');
|
|
73
|
+
const testObservations = [
|
|
74
|
+
{
|
|
75
|
+
id: 'obs-1',
|
|
76
|
+
text: 'Machine learning algorithms require large datasets for training. Deep learning models especially need millions of examples.',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'obs-2',
|
|
80
|
+
text: 'Neural networks are inspired by biological neurons. They consist of layers of interconnected nodes.',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'obs-3',
|
|
84
|
+
text: 'TypeScript provides static typing for JavaScript. This helps catch errors during development.',
|
|
85
|
+
}
|
|
86
|
+
];
|
|
87
|
+
for (const obs of testObservations) {
|
|
88
|
+
const embedding = await embeddingService.embed(obs.text);
|
|
89
|
+
const now = Date.now() * 1000; // Microseconds for Validity
|
|
90
|
+
await db.run(`
|
|
91
|
+
?[id, created_at, entity_id, session_id, task_id, text, embedding, metadata] <- [[
|
|
92
|
+
$id,
|
|
93
|
+
$created_at,
|
|
94
|
+
'test-entity',
|
|
95
|
+
null,
|
|
96
|
+
null,
|
|
97
|
+
$text,
|
|
98
|
+
$embedding,
|
|
99
|
+
{}
|
|
100
|
+
]]
|
|
101
|
+
:put observation {id, created_at => entity_id, session_id, task_id, text, embedding, metadata}
|
|
102
|
+
`, { id: obs.id, created_at: now, text: obs.text, embedding });
|
|
103
|
+
}
|
|
104
|
+
console.log(`✓ Created ${testObservations.length} initial observations\n`);
|
|
105
|
+
// Test 3: Add new observation and trigger evolution
|
|
106
|
+
console.log('Test 3: Adding new observation with automatic evolution...');
|
|
107
|
+
const newObsId = 'obs-4';
|
|
108
|
+
const newObsText = 'Deep learning is a subset of machine learning that uses neural networks with multiple layers. Training requires substantial computational resources and large datasets.';
|
|
109
|
+
const newObsEmbedding = await embeddingService.embed(newObsText);
|
|
110
|
+
// Add to database
|
|
111
|
+
const now = Date.now() * 1000; // Microseconds for Validity
|
|
112
|
+
await db.run(`
|
|
113
|
+
?[id, created_at, entity_id, session_id, task_id, text, embedding, metadata] <- [[
|
|
114
|
+
$id,
|
|
115
|
+
$created_at,
|
|
116
|
+
'test-entity',
|
|
117
|
+
null,
|
|
118
|
+
null,
|
|
119
|
+
$text,
|
|
120
|
+
$embedding,
|
|
121
|
+
{}
|
|
122
|
+
]]
|
|
123
|
+
:put observation {id, created_at => entity_id, session_id, task_id, text, embedding, metadata}
|
|
124
|
+
`, { id: newObsId, created_at: now, text: newObsText, embedding: newObsEmbedding });
|
|
125
|
+
// Trigger evolution
|
|
126
|
+
const enrichmentResult = await zettelService.enrichObservation(newObsId, newObsText, newObsEmbedding, 'test-entity');
|
|
127
|
+
console.log(`\nEnrichment Result:`);
|
|
128
|
+
console.log(` Observation ID: ${enrichmentResult.observationId}`);
|
|
129
|
+
console.log(` Extracted Keywords: ${enrichmentResult.extractedKeywords.join(', ')}`);
|
|
130
|
+
console.log(` Added Tags: ${enrichmentResult.addedTags.length > 0 ? enrichmentResult.addedTags.join(', ') : 'none'}`);
|
|
131
|
+
console.log(` Related Notes Found: ${enrichmentResult.relatedNotes.length}`);
|
|
132
|
+
console.log(` Bidirectional Links Created: ${enrichmentResult.createdLinks}`);
|
|
133
|
+
console.log(` Summary: ${enrichmentResult.evolutionSummary}\n`);
|
|
134
|
+
if (enrichmentResult.relatedNotes.length > 0) {
|
|
135
|
+
console.log(`Related Notes:`);
|
|
136
|
+
for (const related of enrichmentResult.relatedNotes) {
|
|
137
|
+
console.log(` - ${related.observationId} (similarity: ${related.similarity.toFixed(3)})`);
|
|
138
|
+
console.log(` Type: ${related.connectionType}`);
|
|
139
|
+
console.log(` Reason: ${related.reason}`);
|
|
140
|
+
console.log(` Shared Keywords: ${related.sharedKeywords.join(', ') || 'none'}`);
|
|
141
|
+
console.log(` Text: ${related.text.substring(0, 80)}...`);
|
|
142
|
+
}
|
|
143
|
+
console.log();
|
|
144
|
+
}
|
|
145
|
+
// Test 4: Verify bidirectional links
|
|
146
|
+
console.log('Test 4: Verifying bidirectional links...');
|
|
147
|
+
const linksResult = await db.run(`
|
|
148
|
+
?[from_id, to_id, relation_type, strength] :=
|
|
149
|
+
*relationship{from_id, to_id, relation_type, strength},
|
|
150
|
+
relation_type == 'zettelkasten_link'
|
|
151
|
+
`);
|
|
152
|
+
console.log(`✓ Found ${linksResult.rows.length} zettelkasten links`);
|
|
153
|
+
for (const [from, to, type, strength] of linksResult.rows) {
|
|
154
|
+
console.log(` ${from} → ${to} (strength: ${strength.toFixed(3)})`);
|
|
155
|
+
}
|
|
156
|
+
console.log();
|
|
157
|
+
// Test 5: Check metadata enrichment
|
|
158
|
+
console.log('Test 5: Checking metadata enrichment...');
|
|
159
|
+
const metadataResult = await db.run(`
|
|
160
|
+
?[id, metadata] :=
|
|
161
|
+
*observation{id, metadata},
|
|
162
|
+
metadata != null,
|
|
163
|
+
get(metadata, "zettelkasten_enriched") == true
|
|
164
|
+
`);
|
|
165
|
+
console.log(`✓ ${metadataResult.rows.length} observations have been enriched`);
|
|
166
|
+
for (const [id, metadata] of metadataResult.rows) {
|
|
167
|
+
const meta = metadata;
|
|
168
|
+
console.log(` ${id}:`);
|
|
169
|
+
if (meta.zettelkasten_keywords) {
|
|
170
|
+
const keywords = JSON.parse(meta.zettelkasten_keywords);
|
|
171
|
+
console.log(` Keywords: ${keywords.join(', ')}`);
|
|
172
|
+
}
|
|
173
|
+
if (meta.zettelkasten_related) {
|
|
174
|
+
const related = JSON.parse(meta.zettelkasten_related);
|
|
175
|
+
console.log(` Related: ${related.length} note(s)`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
console.log();
|
|
179
|
+
// Test 6: Get evolution statistics
|
|
180
|
+
console.log('Test 6: Getting evolution statistics...');
|
|
181
|
+
const stats = await zettelService.getEvolutionStats();
|
|
182
|
+
console.log(`Total Observations: ${stats.totalObservations}`);
|
|
183
|
+
console.log(`Enriched Observations: ${stats.enrichedObservations}`);
|
|
184
|
+
console.log(`Total Zettelkasten Links: ${stats.totalLinks}`);
|
|
185
|
+
console.log(`Average Links per Note: ${stats.averageLinksPerNote.toFixed(2)}`);
|
|
186
|
+
console.log();
|
|
187
|
+
// Test 7: Test keyword extraction
|
|
188
|
+
console.log('Test 7: Testing keyword extraction...');
|
|
189
|
+
const testTexts = [
|
|
190
|
+
'Machine learning algorithms require training data',
|
|
191
|
+
'The quick brown fox jumps over the lazy dog',
|
|
192
|
+
'TypeScript TypeScript TypeScript is great for development development'
|
|
193
|
+
];
|
|
194
|
+
for (const text of testTexts) {
|
|
195
|
+
const keywords = zettelService.extractKeywords(text);
|
|
196
|
+
console.log(`Text: "${text.substring(0, 50)}..."`);
|
|
197
|
+
console.log(`Keywords: ${keywords.join(', ') || 'none'}\n`);
|
|
198
|
+
}
|
|
199
|
+
// Test 8: Test tag extraction
|
|
200
|
+
console.log('Test 8: Testing tag extraction...');
|
|
201
|
+
const tagTexts = [
|
|
202
|
+
'This is about #machinelearning and #ai',
|
|
203
|
+
'Category: programming, Type: tutorial',
|
|
204
|
+
'No tags here'
|
|
205
|
+
];
|
|
206
|
+
for (const text of tagTexts) {
|
|
207
|
+
const tags = zettelService.extractTags(text);
|
|
208
|
+
console.log(`Text: "${text}"`);
|
|
209
|
+
console.log(`Tags: ${tags.join(', ') || 'none'}\n`);
|
|
210
|
+
}
|
|
211
|
+
// Test 9: Add another observation to see cascading evolution
|
|
212
|
+
console.log('Test 9: Testing cascading evolution with another observation...');
|
|
213
|
+
const cascadeObsId = 'obs-5';
|
|
214
|
+
const cascadeObsText = 'Training neural networks requires backpropagation algorithm. Machine learning models learn from data patterns.';
|
|
215
|
+
const cascadeObsEmbedding = await embeddingService.embed(cascadeObsText);
|
|
216
|
+
const now2 = Date.now() * 1000; // Microseconds for Validity
|
|
217
|
+
await db.run(`
|
|
218
|
+
?[id, created_at, entity_id, session_id, task_id, text, embedding, metadata] <- [[
|
|
219
|
+
$id,
|
|
220
|
+
$created_at,
|
|
221
|
+
'test-entity',
|
|
222
|
+
null,
|
|
223
|
+
null,
|
|
224
|
+
$text,
|
|
225
|
+
$embedding,
|
|
226
|
+
{}
|
|
227
|
+
]]
|
|
228
|
+
:put observation {id, created_at => entity_id, session_id, task_id, text, embedding, metadata}
|
|
229
|
+
`, { id: cascadeObsId, created_at: now2, text: cascadeObsText, embedding: cascadeObsEmbedding });
|
|
230
|
+
const cascadeResult = await zettelService.enrichObservation(cascadeObsId, cascadeObsText, cascadeObsEmbedding, 'test-entity');
|
|
231
|
+
console.log(`✓ Cascade enrichment completed`);
|
|
232
|
+
console.log(` Related Notes: ${cascadeResult.relatedNotes.length}`);
|
|
233
|
+
console.log(` New Links: ${cascadeResult.createdLinks}`);
|
|
234
|
+
console.log(` Keywords: ${cascadeResult.extractedKeywords.join(', ')}`);
|
|
235
|
+
console.log();
|
|
236
|
+
// Final stats
|
|
237
|
+
const finalStats = await zettelService.getEvolutionStats();
|
|
238
|
+
console.log('Final Statistics:');
|
|
239
|
+
console.log(` Total Observations: ${finalStats.totalObservations}`);
|
|
240
|
+
console.log(` Enriched: ${finalStats.enrichedObservations} (${(finalStats.enrichedObservations / finalStats.totalObservations * 100).toFixed(1)}%)`);
|
|
241
|
+
console.log(` Total Links: ${finalStats.totalLinks}`);
|
|
242
|
+
console.log(` Avg Links/Note: ${finalStats.averageLinksPerNote.toFixed(2)}`);
|
|
243
|
+
console.log();
|
|
244
|
+
console.log('=== All Tests Completed Successfully ===');
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error('Test failed:', error);
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
db.close();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Run tests
|
|
255
|
+
testZettelkastenEvolution().catch(console.error);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cozo_node_1 = require("cozo-node");
|
|
4
|
+
const embedding_service_1 = require("./embedding-service");
|
|
5
|
+
const zettelkasten_evolution_1 = require("./zettelkasten-evolution");
|
|
6
|
+
async function testZettelkastenFixed() {
|
|
7
|
+
console.log('=== Testing Zettelkasten Evolution with Fixed HNSW Query ===\n');
|
|
8
|
+
// Use the actual database
|
|
9
|
+
const db = new cozo_node_1.CozoDb('sqlite', 'memory_db.cozo.db');
|
|
10
|
+
const embeddings = new embedding_service_1.EmbeddingService();
|
|
11
|
+
const zettelkasten = new zettelkasten_evolution_1.ZettelkastenEvolutionService(db, embeddings, {
|
|
12
|
+
enableEvolution: true,
|
|
13
|
+
similarityThreshold: 0.7,
|
|
14
|
+
maxRelatedNotes: 5,
|
|
15
|
+
minKeywordFrequency: 1,
|
|
16
|
+
autoExtractKeywords: true,
|
|
17
|
+
autoBidirectionalLinks: true,
|
|
18
|
+
enrichmentDepth: 'shallow'
|
|
19
|
+
});
|
|
20
|
+
try {
|
|
21
|
+
// Get a sample observation from the database
|
|
22
|
+
const obsResult = await db.run(`
|
|
23
|
+
?[id, entity_id, text, embedding] :=
|
|
24
|
+
*observation{id, entity_id, text, embedding, @ "NOW"}
|
|
25
|
+
:limit 1
|
|
26
|
+
`);
|
|
27
|
+
if (obsResult.rows.length === 0) {
|
|
28
|
+
console.log('No observations found in database. Please add some data first.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const [obsId, entityId, text, embedding] = obsResult.rows[0];
|
|
32
|
+
console.log(`Testing with observation: ${obsId}`);
|
|
33
|
+
console.log(`Text: ${text}\n`);
|
|
34
|
+
// Test keyword extraction
|
|
35
|
+
console.log('1. Testing keyword extraction...');
|
|
36
|
+
const keywords = zettelkasten.extractKeywords(text);
|
|
37
|
+
console.log(` Extracted keywords: ${keywords.join(', ')}\n`);
|
|
38
|
+
// Test tag extraction
|
|
39
|
+
console.log('2. Testing tag extraction...');
|
|
40
|
+
const tags = zettelkasten.extractTags(text);
|
|
41
|
+
console.log(` Extracted tags: ${tags.join(', ')}\n`);
|
|
42
|
+
// Test finding related notes (this was failing before)
|
|
43
|
+
console.log('3. Testing HNSW semantic search for related notes...');
|
|
44
|
+
const relatedNotes = await zettelkasten.findRelatedNotes(obsId, text, embedding);
|
|
45
|
+
console.log(` Found ${relatedNotes.length} related notes:`);
|
|
46
|
+
relatedNotes.forEach((note, i) => {
|
|
47
|
+
console.log(` ${i + 1}. ${note.observationId} (similarity: ${note.similarity.toFixed(3)})`);
|
|
48
|
+
console.log(` Connection: ${note.connectionType} - ${note.reason}`);
|
|
49
|
+
console.log(` Shared keywords: ${note.sharedKeywords.join(', ')}`);
|
|
50
|
+
});
|
|
51
|
+
console.log();
|
|
52
|
+
// Test full enrichment
|
|
53
|
+
console.log('4. Testing full observation enrichment...');
|
|
54
|
+
const enrichmentResult = await zettelkasten.enrichObservation(obsId, text, embedding, entityId);
|
|
55
|
+
console.log(` ${enrichmentResult.evolutionSummary}`);
|
|
56
|
+
console.log(` Keywords: ${enrichmentResult.extractedKeywords.join(', ')}`);
|
|
57
|
+
console.log(` Tags: ${enrichmentResult.addedTags.join(', ')}`);
|
|
58
|
+
console.log(` Related notes: ${enrichmentResult.relatedNotes.length}`);
|
|
59
|
+
console.log(` Created links: ${enrichmentResult.createdLinks}\n`);
|
|
60
|
+
// Test evolution stats
|
|
61
|
+
console.log('5. Testing evolution statistics...');
|
|
62
|
+
const stats = await zettelkasten.getEvolutionStats();
|
|
63
|
+
console.log(` Total observations: ${stats.totalObservations}`);
|
|
64
|
+
console.log(` Enriched observations: ${stats.enrichedObservations}`);
|
|
65
|
+
console.log(` Total links: ${stats.totalLinks}`);
|
|
66
|
+
console.log(` Average links per note: ${stats.averageLinksPerNote.toFixed(2)}\n`);
|
|
67
|
+
console.log('✅ All tests passed! HNSW query is working correctly.');
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('❌ Test failed:', error);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
testZettelkastenFixed().catch(console.error);
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cozo_node_1 = require("cozo-node");
|
|
4
|
+
const zettelkasten_evolution_1 = require("./zettelkasten-evolution");
|
|
5
|
+
const embedding_service_1 = require("./embedding-service");
|
|
6
|
+
async function testZettelkastenLive() {
|
|
7
|
+
console.log('=== Zettelkasten Live Test with Existing Data ===\n');
|
|
8
|
+
// Open the actual database file
|
|
9
|
+
const db = new cozo_node_1.CozoDb('sqlite', 'memory_db.cozo.db');
|
|
10
|
+
const embeddingService = new embedding_service_1.EmbeddingService();
|
|
11
|
+
const zettelService = new zettelkasten_evolution_1.ZettelkastenEvolutionService(db, embeddingService, {
|
|
12
|
+
enableEvolution: true,
|
|
13
|
+
similarityThreshold: 0.7,
|
|
14
|
+
maxRelatedNotes: 5,
|
|
15
|
+
minKeywordFrequency: 1, // Lower for testing
|
|
16
|
+
autoExtractKeywords: true,
|
|
17
|
+
autoBidirectionalLinks: true,
|
|
18
|
+
enrichmentDepth: 'shallow'
|
|
19
|
+
});
|
|
20
|
+
try {
|
|
21
|
+
// Test 1: Get current evolution stats
|
|
22
|
+
console.log('Test 1: Getting current evolution statistics...');
|
|
23
|
+
const stats = await zettelService.getEvolutionStats();
|
|
24
|
+
console.log(`Total Observations: ${stats.totalObservations}`);
|
|
25
|
+
console.log(`Enriched Observations: ${stats.enrichedObservations}`);
|
|
26
|
+
console.log(`Total Zettelkasten Links: ${stats.totalLinks}`);
|
|
27
|
+
console.log(`Average Links per Note: ${stats.averageLinksPerNote.toFixed(2)}`);
|
|
28
|
+
console.log();
|
|
29
|
+
// Test 2: Get the last observation we created
|
|
30
|
+
console.log('Test 2: Fetching recent observations...');
|
|
31
|
+
const obsResult = await db.run(`
|
|
32
|
+
?[id, entity_id, text, embedding] :=
|
|
33
|
+
*observation{id, entity_id, text, embedding, @ "NOW"}
|
|
34
|
+
:limit 5
|
|
35
|
+
`);
|
|
36
|
+
if (obsResult.rows.length === 0) {
|
|
37
|
+
console.log('No observations found in database');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(`Found ${obsResult.rows.length} observations\n`);
|
|
41
|
+
// Test 3: Test keyword extraction on existing observations
|
|
42
|
+
console.log('Test 3: Testing keyword extraction...');
|
|
43
|
+
for (const row of obsResult.rows.slice(0, 3)) {
|
|
44
|
+
const text = row[2];
|
|
45
|
+
const keywords = zettelService.extractKeywords(text);
|
|
46
|
+
console.log(`Text: "${text.substring(0, 60)}..."`);
|
|
47
|
+
console.log(`Keywords: ${keywords.join(', ') || 'none'}\n`);
|
|
48
|
+
}
|
|
49
|
+
// Test 4: Test tag extraction
|
|
50
|
+
console.log('Test 4: Testing tag extraction...');
|
|
51
|
+
const testTexts = [
|
|
52
|
+
'This is about #machinelearning and #ai',
|
|
53
|
+
'Category: programming, Type: tutorial',
|
|
54
|
+
obsResult.rows[0][2]
|
|
55
|
+
];
|
|
56
|
+
for (const text of testTexts) {
|
|
57
|
+
const tags = zettelService.extractTags(text);
|
|
58
|
+
console.log(`Text: "${text.substring(0, 50)}..."`);
|
|
59
|
+
console.log(`Tags: ${tags.join(', ') || 'none'}\n`);
|
|
60
|
+
}
|
|
61
|
+
// Test 5: Find related notes for the first observation
|
|
62
|
+
console.log('Test 5: Finding related notes...');
|
|
63
|
+
const firstObs = obsResult.rows[0];
|
|
64
|
+
const obsId = firstObs[0];
|
|
65
|
+
const obsText = firstObs[2];
|
|
66
|
+
const obsEmbedding = firstObs[3];
|
|
67
|
+
console.log(`Analyzing observation: ${obsId}`);
|
|
68
|
+
console.log(`Text: "${obsText.substring(0, 80)}..."\n`);
|
|
69
|
+
const relatedNotes = await zettelService.findRelatedNotes(obsId, obsText, obsEmbedding);
|
|
70
|
+
console.log(`Found ${relatedNotes.length} related notes:`);
|
|
71
|
+
for (const related of relatedNotes) {
|
|
72
|
+
console.log(` - ${related.observationId}`);
|
|
73
|
+
console.log(` Similarity: ${related.similarity.toFixed(3)}`);
|
|
74
|
+
console.log(` Type: ${related.connectionType}`);
|
|
75
|
+
console.log(` Reason: ${related.reason}`);
|
|
76
|
+
console.log(` Shared Keywords: ${related.sharedKeywords.join(', ') || 'none'}`);
|
|
77
|
+
console.log(` Text: ${related.text.substring(0, 60)}...`);
|
|
78
|
+
console.log();
|
|
79
|
+
}
|
|
80
|
+
// Test 6: Enrich one observation
|
|
81
|
+
if (obsResult.rows.length > 0) {
|
|
82
|
+
console.log('Test 6: Enriching an observation...');
|
|
83
|
+
const testObs = obsResult.rows[0];
|
|
84
|
+
const testId = testObs[0];
|
|
85
|
+
const testText = testObs[2];
|
|
86
|
+
const testEmbedding = testObs[3];
|
|
87
|
+
const testEntityId = testObs[1];
|
|
88
|
+
const enrichmentResult = await zettelService.enrichObservation(testId, testText, testEmbedding, testEntityId);
|
|
89
|
+
console.log(`Enrichment Result:`);
|
|
90
|
+
console.log(` Observation ID: ${enrichmentResult.observationId}`);
|
|
91
|
+
console.log(` Extracted Keywords: ${enrichmentResult.extractedKeywords.join(', ')}`);
|
|
92
|
+
console.log(` Added Tags: ${enrichmentResult.addedTags.length > 0 ? enrichmentResult.addedTags.join(', ') : 'none'}`);
|
|
93
|
+
console.log(` Related Notes: ${enrichmentResult.relatedNotes.length}`);
|
|
94
|
+
console.log(` Links Created: ${enrichmentResult.createdLinks}`);
|
|
95
|
+
console.log(` Summary: ${enrichmentResult.evolutionSummary}`);
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
// Test 7: Check final stats
|
|
99
|
+
console.log('Test 7: Final statistics...');
|
|
100
|
+
const finalStats = await zettelService.getEvolutionStats();
|
|
101
|
+
console.log(`Total Observations: ${finalStats.totalObservations}`);
|
|
102
|
+
console.log(`Enriched: ${finalStats.enrichedObservations}`);
|
|
103
|
+
console.log(`Total Links: ${finalStats.totalLinks}`);
|
|
104
|
+
console.log(`Avg Links/Note: ${finalStats.averageLinksPerNote.toFixed(2)}`);
|
|
105
|
+
console.log();
|
|
106
|
+
console.log('=== All Tests Completed Successfully ===');
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('Test failed:', error);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
db.close();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Run tests
|
|
117
|
+
testZettelkastenLive().catch(console.error);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const index_1 = require("./index");
|
|
5
|
+
async function testZettelkastenMCPTools() {
|
|
6
|
+
console.log("=== Testing Zettelkasten MCP Tools ===\n");
|
|
7
|
+
const server = new index_1.MemoryServer();
|
|
8
|
+
await server.initPromise;
|
|
9
|
+
try {
|
|
10
|
+
// Step 1: Create test entity
|
|
11
|
+
console.log("1. Creating test entity...");
|
|
12
|
+
const entityResult = await server.createEntity({
|
|
13
|
+
name: "Zettelkasten Test",
|
|
14
|
+
type: "TestEntity",
|
|
15
|
+
metadata: { purpose: "testing" }
|
|
16
|
+
});
|
|
17
|
+
console.log("✓ Entity created:", entityResult.id);
|
|
18
|
+
// Step 2: Add multiple observations
|
|
19
|
+
console.log("\n2. Adding test observations...");
|
|
20
|
+
const observations = [
|
|
21
|
+
"Machine learning is a subset of artificial intelligence focused on learning from data.",
|
|
22
|
+
"Neural networks are computational models inspired by biological neurons in the brain.",
|
|
23
|
+
"Deep learning uses multiple layers of neural networks to learn hierarchical representations.",
|
|
24
|
+
"Transformers revolutionized NLP by using self-attention mechanisms instead of recurrence.",
|
|
25
|
+
"Large language models like GPT are trained on massive text corpora using transformers."
|
|
26
|
+
];
|
|
27
|
+
const obsIds = [];
|
|
28
|
+
for (const text of observations) {
|
|
29
|
+
const obs = await server.addObservation({
|
|
30
|
+
entity_id: entityResult.id,
|
|
31
|
+
text: text,
|
|
32
|
+
metadata: { test: true }
|
|
33
|
+
});
|
|
34
|
+
if (obs.id) {
|
|
35
|
+
obsIds.push(obs.id);
|
|
36
|
+
console.log(`✓ Observation added: ${obs.id.substring(0, 8)}...`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Step 3: Test get_zettelkasten_stats via direct method call
|
|
40
|
+
console.log("\n3. Testing getZettelkastenStats...");
|
|
41
|
+
const stats = await server.getZettelkastenService().getEvolutionStats();
|
|
42
|
+
console.log("✓ Stats retrieved:");
|
|
43
|
+
console.log(` - Total observations: ${stats.totalObservations}`);
|
|
44
|
+
console.log(` - Enriched observations: ${stats.enrichedObservations}`);
|
|
45
|
+
console.log(` - Total links: ${stats.totalLinks}`);
|
|
46
|
+
console.log(` - Average links per note: ${stats.averageLinksPerNote.toFixed(2)}`);
|
|
47
|
+
console.log(` - Top keywords: ${stats.topKeywords.slice(0, 5).map((k) => k.keyword).join(", ")}`);
|
|
48
|
+
// Step 4: Test enrich_observation via getting observation data and calling enrichment
|
|
49
|
+
console.log("\n4. Testing enrichObservation...");
|
|
50
|
+
const obsRes = await server.db.run(`?[obs_id, entity_id, text, embedding] := *observation{id: $id, entity_id, text, embedding, @ "NOW"}, obs_id = $id`, { id: obsIds[0] });
|
|
51
|
+
if (obsRes.rows.length > 0) {
|
|
52
|
+
const [obs_id, entity_id, text, embedding] = obsRes.rows[0];
|
|
53
|
+
const enrichData = await server.getZettelkastenService().enrichObservation(obs_id, text, embedding, entity_id);
|
|
54
|
+
console.log("✓ Observation enriched:");
|
|
55
|
+
console.log(` - Observation ID: ${enrichData.observationId}`);
|
|
56
|
+
console.log(` - Extracted keywords: ${enrichData.extractedKeywords.join(", ")}`);
|
|
57
|
+
console.log(` - Added tags: ${enrichData.addedTags.join(", ")}`);
|
|
58
|
+
console.log(` - Created links: ${enrichData.createdLinks}`);
|
|
59
|
+
console.log(` - Related notes: ${enrichData.relatedNotes.length}`);
|
|
60
|
+
console.log(` - Evolution summary: ${enrichData.evolutionSummary}`);
|
|
61
|
+
}
|
|
62
|
+
// Step 5: Verify stats updated
|
|
63
|
+
console.log("\n5. Verifying stats after enrichment...");
|
|
64
|
+
const stats2 = await server.getZettelkastenService().getEvolutionStats();
|
|
65
|
+
console.log("✓ Updated stats:");
|
|
66
|
+
console.log(` - Total observations: ${stats2.totalObservations}`);
|
|
67
|
+
console.log(` - Enriched observations: ${stats2.enrichedObservations}`);
|
|
68
|
+
console.log(` - Total links: ${stats2.totalLinks}`);
|
|
69
|
+
console.log(` - Average links per note: ${stats2.averageLinksPerNote.toFixed(2)}`);
|
|
70
|
+
// Step 6: Enrich another observation
|
|
71
|
+
console.log("\n6. Enriching second observation...");
|
|
72
|
+
const obsRes2 = await server.db.run(`?[obs_id, entity_id, text, embedding] := *observation{id: $id, entity_id, text, embedding, @ "NOW"}, obs_id = $id`, { id: obsIds[1] });
|
|
73
|
+
if (obsRes2.rows.length > 0) {
|
|
74
|
+
const [obs_id, entity_id, text, embedding] = obsRes2.rows[0];
|
|
75
|
+
const enrichData2 = await server.getZettelkastenService().enrichObservation(obs_id, text, embedding, entity_id);
|
|
76
|
+
console.log("✓ Second observation enriched:");
|
|
77
|
+
console.log(` - Created links: ${enrichData2.createdLinks}`);
|
|
78
|
+
console.log(` - Related notes: ${enrichData2.relatedNotes.length}`);
|
|
79
|
+
}
|
|
80
|
+
// Step 7: Final stats
|
|
81
|
+
console.log("\n7. Final statistics...");
|
|
82
|
+
const stats3 = await server.getZettelkastenService().getEvolutionStats();
|
|
83
|
+
console.log("✓ Final stats:");
|
|
84
|
+
console.log(` - Total observations: ${stats3.totalObservations}`);
|
|
85
|
+
console.log(` - Enriched observations: ${stats3.enrichedObservations}`);
|
|
86
|
+
console.log(` - Total links: ${stats3.totalLinks}`);
|
|
87
|
+
console.log(` - Average links per note: ${stats3.averageLinksPerNote.toFixed(2)}`);
|
|
88
|
+
console.log(` - Top keywords: ${stats3.topKeywords.slice(0, 10).map((k) => `${k.keyword}(${k.frequency})`).join(", ")}`);
|
|
89
|
+
console.log("\n=== ✓ All Zettelkasten MCP Tools Tests Passed ===");
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error("\n✗ Test failed:", error);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
testZettelkastenMCPTools();
|