cozo-memory 1.1.4 โ 1.1.6
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/README.md +161 -1159
- package/dist/adaptive-query-fusion.js +397 -0
- package/dist/dynamic-fusion.js +63 -8
- package/dist/explainable-retrieval.js +552 -0
- package/dist/hierarchical-memory.js +358 -0
- package/dist/proactive-suggestions.js +382 -0
- package/dist/temporal-conflict-resolution.js +386 -0
- package/dist/temporal-pattern-detection-backup.js +358 -0
- package/dist/temporal-pattern-detection.js +482 -0
- package/dist/test-adaptive-query-fusion.js +208 -0
- package/dist/test-explainable-retrieval.js +408 -0
- package/dist/test-hierarchical-and-patterns.js +17 -0
- package/dist/test-hierarchical-memory.js +205 -0
- package/dist/test-proactive-suggestions.js +240 -0
- package/dist/test-temporal-conflict-resolution.js +228 -0
- package/dist/test-temporal-patterns.js +317 -0
- package/package.json +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const cozo_node_1 = require("cozo-node");
|
|
37
|
+
const embedding_service_1 = require("./embedding-service");
|
|
38
|
+
const proactive_suggestions_1 = require("./proactive-suggestions");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const DB_PATH = 'test_proactive.db';
|
|
41
|
+
async function runTests() {
|
|
42
|
+
console.error('[Test] Starting Proactive Suggestions Tests...\n');
|
|
43
|
+
// Clean up old database
|
|
44
|
+
if (fs.existsSync(DB_PATH)) {
|
|
45
|
+
try {
|
|
46
|
+
fs.unlinkSync(DB_PATH);
|
|
47
|
+
}
|
|
48
|
+
catch (e) { }
|
|
49
|
+
}
|
|
50
|
+
const db = new cozo_node_1.CozoDb('sqlite', DB_PATH);
|
|
51
|
+
const embeddings = new embedding_service_1.EmbeddingService();
|
|
52
|
+
// Create a wrapper to make ProactiveSuggestionsService work with CozoDb
|
|
53
|
+
const dbWrapper = {
|
|
54
|
+
getEntity: async (id) => {
|
|
55
|
+
const res = await db.run('?[name, type, embedding] := *entity{id: $id, name, type, embedding, @ "NOW"}', { id });
|
|
56
|
+
if (res.rows.length === 0)
|
|
57
|
+
return null;
|
|
58
|
+
return {
|
|
59
|
+
id,
|
|
60
|
+
name: res.rows[0][0],
|
|
61
|
+
type: res.rows[0][1],
|
|
62
|
+
embedding: res.rows[0][2],
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
getRelations: async (fromId, toId) => {
|
|
66
|
+
let query = '?[from_id, to_id, relation_type, strength] := *relationship{from_id, to_id, relation_type, strength, @ "NOW"}';
|
|
67
|
+
const params = {};
|
|
68
|
+
if (fromId) {
|
|
69
|
+
query += ', from_id = $from_id';
|
|
70
|
+
params.from_id = fromId;
|
|
71
|
+
}
|
|
72
|
+
if (toId) {
|
|
73
|
+
query += ', to_id = $to_id';
|
|
74
|
+
params.to_id = toId;
|
|
75
|
+
}
|
|
76
|
+
const res = await db.run(query, params);
|
|
77
|
+
return res.rows.map((r) => ({
|
|
78
|
+
from_id: r[0],
|
|
79
|
+
to_id: r[1],
|
|
80
|
+
relation_type: r[2],
|
|
81
|
+
strength: r[3],
|
|
82
|
+
}));
|
|
83
|
+
},
|
|
84
|
+
vectorSearchEntity: async (embedding, limit) => {
|
|
85
|
+
const res = await db.run('?[id, name, type] := *entity{id, name, type, @ "NOW"} :limit $limit', { limit });
|
|
86
|
+
return res.rows.map((r) => [r[0], r[1], r[2], {}, 0.8]);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
const suggestions = new proactive_suggestions_1.ProactiveSuggestionsService(dbWrapper, embeddings, {
|
|
90
|
+
maxSuggestions: 5,
|
|
91
|
+
minConfidence: 0.5,
|
|
92
|
+
enableVectorSimilarity: true,
|
|
93
|
+
enableCommonNeighbors: true,
|
|
94
|
+
enableInference: true,
|
|
95
|
+
enableGraphProximity: true,
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
// Setup: Create test entities and relationships
|
|
99
|
+
console.error('[Test] Setting up test data...');
|
|
100
|
+
const EMBEDDING_DIM = embeddings.getDimensions();
|
|
101
|
+
// Create entity table
|
|
102
|
+
try {
|
|
103
|
+
await db.run(`{:create entity {id: String, created_at: Validity => name: String, type: String, embedding: <F32; ${EMBEDDING_DIM}>, name_embedding: <F32; ${EMBEDDING_DIM}>, metadata: Json}}`);
|
|
104
|
+
}
|
|
105
|
+
catch (e) { }
|
|
106
|
+
// Create relationship table
|
|
107
|
+
try {
|
|
108
|
+
await db.run('{:create relationship {from_id: String, to_id: String, relation_type: String, created_at: Validity => strength: Float, metadata: Json}}');
|
|
109
|
+
}
|
|
110
|
+
catch (e) { }
|
|
111
|
+
// Create entities
|
|
112
|
+
const aliceEmb = await embeddings.embed('Alice Developer');
|
|
113
|
+
const bobEmb = await embeddings.embed('Bob Engineer');
|
|
114
|
+
const charlieEmb = await embeddings.embed('Charlie Manager');
|
|
115
|
+
const projectXEmb = await embeddings.embed('Project X Development');
|
|
116
|
+
const projectYEmb = await embeddings.embed('Project Y Research');
|
|
117
|
+
const now = Date.now() * 1000;
|
|
118
|
+
await db.run(`
|
|
119
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] <- [
|
|
120
|
+
['alice-id', [${now}, true], 'Alice', 'Person', $emb, $emb, {}]
|
|
121
|
+
] :insert entity {id, created_at => name, type, embedding, name_embedding, metadata}
|
|
122
|
+
`, { emb: aliceEmb });
|
|
123
|
+
await db.run(`
|
|
124
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] <- [
|
|
125
|
+
['bob-id', [${now}, true], 'Bob', 'Person', $emb, $emb, {}]
|
|
126
|
+
] :insert entity {id, created_at => name, type, embedding, name_embedding, metadata}
|
|
127
|
+
`, { emb: bobEmb });
|
|
128
|
+
await db.run(`
|
|
129
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] <- [
|
|
130
|
+
['charlie-id', [${now}, true], 'Charlie', 'Person', $emb, $emb, {}]
|
|
131
|
+
] :insert entity {id, created_at => name, type, embedding, name_embedding, metadata}
|
|
132
|
+
`, { emb: charlieEmb });
|
|
133
|
+
await db.run(`
|
|
134
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] <- [
|
|
135
|
+
['project-x-id', [${now}, true], 'Project X', 'Project', $emb, $emb, {}]
|
|
136
|
+
] :insert entity {id, created_at => name, type, embedding, name_embedding, metadata}
|
|
137
|
+
`, { emb: projectXEmb });
|
|
138
|
+
await db.run(`
|
|
139
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] <- [
|
|
140
|
+
['project-y-id', [${now}, true], 'Project Y', 'Project', $emb, $emb, {}]
|
|
141
|
+
] :insert entity {id, created_at => name, type, embedding, name_embedding, metadata}
|
|
142
|
+
`, { emb: projectYEmb });
|
|
143
|
+
// Create relationships
|
|
144
|
+
await db.run(`
|
|
145
|
+
?[from_id, to_id, relation_type, created_at, strength, metadata] <- [
|
|
146
|
+
['alice-id', 'project-x-id', 'works_on', [${now}, true], 1.0, {}],
|
|
147
|
+
['bob-id', 'project-x-id', 'works_on', [${now}, true], 1.0, {}],
|
|
148
|
+
['charlie-id', 'alice-id', 'manages', [${now}, true], 0.9, {}],
|
|
149
|
+
['bob-id', 'project-y-id', 'works_on', [${now}, true], 0.8, {}],
|
|
150
|
+
['alice-id', 'bob-id', 'colleague_of', [${now}, true], 0.85, {}]
|
|
151
|
+
] :insert relationship {from_id, to_id, relation_type, created_at => strength, metadata}
|
|
152
|
+
`);
|
|
153
|
+
console.error('[Test] Test data created.\n');
|
|
154
|
+
// Test 1: Vector Similarity
|
|
155
|
+
console.error('[Test 1] Vector Similarity Discovery');
|
|
156
|
+
const vectorSuggestions = await suggestions.suggestConnections('alice-id');
|
|
157
|
+
console.error(` Found ${vectorSuggestions.length} suggestions for Alice`);
|
|
158
|
+
vectorSuggestions.forEach(s => {
|
|
159
|
+
console.error(` - ${s.entity_name} (${s.source}): confidence=${s.confidence.toFixed(2)}`);
|
|
160
|
+
});
|
|
161
|
+
console.error('');
|
|
162
|
+
// Test 2: Common Neighbors
|
|
163
|
+
console.error('[Test 2] Common Neighbors Detection');
|
|
164
|
+
const commonNeighborSuggestions = vectorSuggestions.filter(s => s.source === proactive_suggestions_1.SuggestionSource.COMMON_NEIGHBORS);
|
|
165
|
+
console.error(` Found ${commonNeighborSuggestions.length} common neighbor suggestions`);
|
|
166
|
+
commonNeighborSuggestions.forEach(s => {
|
|
167
|
+
console.error(` - ${s.entity_name}: ${s.reason}`);
|
|
168
|
+
});
|
|
169
|
+
console.error('');
|
|
170
|
+
// Test 3: Graph Proximity
|
|
171
|
+
console.error('[Test 3] Graph Proximity Search');
|
|
172
|
+
const graphProximitySuggestions = vectorSuggestions.filter(s => s.source === proactive_suggestions_1.SuggestionSource.GRAPH_PROXIMITY);
|
|
173
|
+
console.error(` Found ${graphProximitySuggestions.length} graph proximity suggestions`);
|
|
174
|
+
graphProximitySuggestions.forEach(s => {
|
|
175
|
+
console.error(` - ${s.entity_name}: ${s.reason}`);
|
|
176
|
+
});
|
|
177
|
+
console.error('');
|
|
178
|
+
// Test 4: Inference
|
|
179
|
+
console.error('[Test 4] Inference-Based Suggestions');
|
|
180
|
+
const inferenceSuggestions = vectorSuggestions.filter(s => s.source === proactive_suggestions_1.SuggestionSource.INFERENCE);
|
|
181
|
+
console.error(` Found ${inferenceSuggestions.length} inferred suggestions`);
|
|
182
|
+
inferenceSuggestions.forEach(s => {
|
|
183
|
+
console.error(` - ${s.entity_name}: ${s.reason}`);
|
|
184
|
+
});
|
|
185
|
+
console.error('');
|
|
186
|
+
// Test 5: Confidence Levels
|
|
187
|
+
console.error('[Test 5] Confidence Level Distribution');
|
|
188
|
+
const highConfidence = vectorSuggestions.filter(s => s.confidence_level === proactive_suggestions_1.ConfidenceLevel.HIGH);
|
|
189
|
+
const mediumConfidence = vectorSuggestions.filter(s => s.confidence_level === proactive_suggestions_1.ConfidenceLevel.MEDIUM);
|
|
190
|
+
const lowConfidence = vectorSuggestions.filter(s => s.confidence_level === proactive_suggestions_1.ConfidenceLevel.LOW);
|
|
191
|
+
console.error(` High: ${highConfidence.length}, Medium: ${mediumConfidence.length}, Low: ${lowConfidence.length}`);
|
|
192
|
+
console.error('');
|
|
193
|
+
// Test 6: Batch Operations
|
|
194
|
+
console.error('[Test 6] Batch Suggestions');
|
|
195
|
+
const batchResults = await suggestions.suggestConnectionsBatch(['alice-id', 'bob-id', 'charlie-id']);
|
|
196
|
+
console.error(` Processed ${batchResults.size} entities`);
|
|
197
|
+
for (const [entityId, suggs] of batchResults.entries()) {
|
|
198
|
+
console.error(` ${entityId}: ${suggs.length} suggestions`);
|
|
199
|
+
}
|
|
200
|
+
console.error('');
|
|
201
|
+
// Test 7: Configuration
|
|
202
|
+
console.error('[Test 7] Configuration Management');
|
|
203
|
+
const config = suggestions.getConfig();
|
|
204
|
+
console.error(` Max Suggestions: ${config.maxSuggestions}`);
|
|
205
|
+
console.error(` Min Confidence: ${config.minConfidence}`);
|
|
206
|
+
console.error(` Vector Similarity Weight: ${config.vectorSimilarityWeight}`);
|
|
207
|
+
console.error(` Common Neighbors Weight: ${config.commonNeighborsWeight}`);
|
|
208
|
+
console.error(` Inference Weight: ${config.inferenceWeight}`);
|
|
209
|
+
console.error(` Graph Proximity Weight: ${config.graphProximityWeight}`);
|
|
210
|
+
console.error('');
|
|
211
|
+
// Test 8: Updated Configuration
|
|
212
|
+
console.error('[Test 8] Updated Configuration');
|
|
213
|
+
suggestions.updateConfig({
|
|
214
|
+
maxSuggestions: 3,
|
|
215
|
+
minConfidence: 0.7,
|
|
216
|
+
});
|
|
217
|
+
const updatedConfig = suggestions.getConfig();
|
|
218
|
+
console.error(` Max Suggestions (updated): ${updatedConfig.maxSuggestions}`);
|
|
219
|
+
console.error(` Min Confidence (updated): ${updatedConfig.minConfidence}`);
|
|
220
|
+
const updatedSuggestions = await suggestions.suggestConnections('alice-id');
|
|
221
|
+
console.error(` Suggestions with new config: ${updatedSuggestions.length}`);
|
|
222
|
+
console.error('');
|
|
223
|
+
console.error('[Test] โ
All tests completed successfully!\n');
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('[Test] โ Error during testing:', error);
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
await db.close();
|
|
230
|
+
// Clean up
|
|
231
|
+
if (fs.existsSync(DB_PATH)) {
|
|
232
|
+
try {
|
|
233
|
+
fs.unlinkSync(DB_PATH);
|
|
234
|
+
}
|
|
235
|
+
catch (e) { }
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Run tests
|
|
240
|
+
runTests().catch(console.error);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Test suite for Temporal Conflict Resolution Service
|
|
4
|
+
*
|
|
5
|
+
* Tests T-GRAG-inspired conflict detection and resolution
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const cozo_node_1 = require("cozo-node");
|
|
9
|
+
const embedding_service_1 = require("./embedding-service");
|
|
10
|
+
const temporal_conflict_resolution_1 = require("./temporal-conflict-resolution");
|
|
11
|
+
const uuid_1 = require("uuid");
|
|
12
|
+
const DB_PATH = 'test_temporal_conflict.cozo.db';
|
|
13
|
+
async function setupDatabase() {
|
|
14
|
+
const db = new cozo_node_1.CozoDb('sqlite', DB_PATH);
|
|
15
|
+
// Create schema matching the main codebase format
|
|
16
|
+
try {
|
|
17
|
+
await db.run(`
|
|
18
|
+
:create entity {
|
|
19
|
+
id: String,
|
|
20
|
+
created_at: Validity
|
|
21
|
+
=>
|
|
22
|
+
name: String,
|
|
23
|
+
type: String,
|
|
24
|
+
embedding: <F32; 1024>,
|
|
25
|
+
name_embedding: <F32; 1024>,
|
|
26
|
+
metadata: Json
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
// Schema already exists, ignore
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await db.run(`
|
|
35
|
+
:create observation {
|
|
36
|
+
id: String,
|
|
37
|
+
created_at: Validity
|
|
38
|
+
=>
|
|
39
|
+
entity_id: String,
|
|
40
|
+
text: String,
|
|
41
|
+
embedding: <F32; 1024>,
|
|
42
|
+
metadata: Json
|
|
43
|
+
}
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
// Schema already exists, ignore
|
|
48
|
+
}
|
|
49
|
+
return db;
|
|
50
|
+
}
|
|
51
|
+
async function createTestEntity(db, embeddings, name) {
|
|
52
|
+
const entityId = (0, uuid_1.v4)();
|
|
53
|
+
const embedding = await embeddings.embed(name);
|
|
54
|
+
const now = Date.now() * 1000; // Convert to microseconds
|
|
55
|
+
await db.run(`
|
|
56
|
+
?[id, created_at, name, type, embedding, name_embedding, metadata] :=
|
|
57
|
+
id = $id,
|
|
58
|
+
created_at = $created_at,
|
|
59
|
+
name = $name,
|
|
60
|
+
type = $type,
|
|
61
|
+
embedding = $embedding,
|
|
62
|
+
name_embedding = $name_embedding,
|
|
63
|
+
metadata = $metadata
|
|
64
|
+
|
|
65
|
+
:put entity {
|
|
66
|
+
id, created_at => name, type, embedding, name_embedding, metadata
|
|
67
|
+
}
|
|
68
|
+
`, {
|
|
69
|
+
id: entityId,
|
|
70
|
+
created_at: [now, true], // Validity format: [timestamp_microseconds, is_valid]
|
|
71
|
+
name,
|
|
72
|
+
type: 'test',
|
|
73
|
+
embedding,
|
|
74
|
+
name_embedding: embedding,
|
|
75
|
+
metadata: {},
|
|
76
|
+
});
|
|
77
|
+
return entityId;
|
|
78
|
+
}
|
|
79
|
+
async function createTestObservation(db, embeddings, entityId, text, createdAt) {
|
|
80
|
+
const obsId = (0, uuid_1.v4)();
|
|
81
|
+
const embedding = await embeddings.embed(text);
|
|
82
|
+
await db.run(`
|
|
83
|
+
?[id, created_at, entity_id, text, embedding, metadata] :=
|
|
84
|
+
id = $id,
|
|
85
|
+
created_at = $created_at,
|
|
86
|
+
entity_id = $entity_id,
|
|
87
|
+
text = $text,
|
|
88
|
+
embedding = $embedding,
|
|
89
|
+
metadata = $metadata
|
|
90
|
+
|
|
91
|
+
:put observation {
|
|
92
|
+
id, created_at => entity_id, text, embedding, metadata
|
|
93
|
+
}
|
|
94
|
+
`, {
|
|
95
|
+
id: obsId,
|
|
96
|
+
created_at: [createdAt * 1000, true], // Validity format: [timestamp_microseconds, is_valid]
|
|
97
|
+
entity_id: entityId,
|
|
98
|
+
text,
|
|
99
|
+
embedding,
|
|
100
|
+
metadata: {},
|
|
101
|
+
});
|
|
102
|
+
return obsId;
|
|
103
|
+
}
|
|
104
|
+
async function runTests() {
|
|
105
|
+
console.log('๐งช Starting Temporal Conflict Resolution Tests\n');
|
|
106
|
+
const db = await setupDatabase();
|
|
107
|
+
const embeddings = new embedding_service_1.EmbeddingService();
|
|
108
|
+
const conflictService = new temporal_conflict_resolution_1.TemporalConflictResolutionService(db, embeddings);
|
|
109
|
+
try {
|
|
110
|
+
// Test 1: Temporal Redundancy Detection
|
|
111
|
+
console.log('Test 1: Temporal Redundancy Detection');
|
|
112
|
+
const entity1 = await createTestEntity(db, embeddings, 'Project Alpha');
|
|
113
|
+
const now = Date.now();
|
|
114
|
+
const oneMonthAgo = now - (30 * 24 * 60 * 60 * 1000);
|
|
115
|
+
await createTestObservation(db, embeddings, entity1, 'Project Alpha is in active development with 5 team members', oneMonthAgo);
|
|
116
|
+
await createTestObservation(db, embeddings, entity1, 'Project Alpha is actively being developed by a team of 5 people', now);
|
|
117
|
+
const conflicts1 = await conflictService.detectConflicts(entity1);
|
|
118
|
+
console.log(`โ Found ${conflicts1.length} conflict(s)`);
|
|
119
|
+
if (conflicts1.length > 0) {
|
|
120
|
+
console.log(` Type: ${conflicts1[0].conflict_type}`);
|
|
121
|
+
console.log(` Confidence: ${(conflicts1[0].confidence * 100).toFixed(1)}%`);
|
|
122
|
+
console.log(` Reason: ${conflicts1[0].reason}`);
|
|
123
|
+
}
|
|
124
|
+
console.log('');
|
|
125
|
+
// Test 2: Semantic Contradiction Detection
|
|
126
|
+
console.log('Test 2: Semantic Contradiction Detection');
|
|
127
|
+
const entity2 = await createTestEntity(db, embeddings, 'Service Beta');
|
|
128
|
+
await createTestObservation(db, embeddings, entity2, 'Service Beta is active and running in production', oneMonthAgo);
|
|
129
|
+
await createTestObservation(db, embeddings, entity2, 'Service Beta has been discontinued and shut down', now);
|
|
130
|
+
const conflicts2 = await conflictService.detectConflicts(entity2);
|
|
131
|
+
console.log(`โ Found ${conflicts2.length} conflict(s)`);
|
|
132
|
+
if (conflicts2.length > 0) {
|
|
133
|
+
console.log(` Type: ${conflicts2[0].conflict_type}`);
|
|
134
|
+
console.log(` Confidence: ${(conflicts2[0].confidence * 100).toFixed(1)}%`);
|
|
135
|
+
console.log(` Reason: ${conflicts2[0].reason}`);
|
|
136
|
+
}
|
|
137
|
+
console.log('');
|
|
138
|
+
// Test 3: Superseded Fact Detection
|
|
139
|
+
console.log('Test 3: Superseded Fact Detection');
|
|
140
|
+
const entity3 = await createTestEntity(db, embeddings, 'Company Revenue');
|
|
141
|
+
await createTestObservation(db, embeddings, entity3, 'Company revenue was $10 million in Q1 2025', oneMonthAgo);
|
|
142
|
+
await createTestObservation(db, embeddings, entity3, 'Updated: Company revenue is now $12 million in Q1 2025 after corrections', now);
|
|
143
|
+
const conflicts3 = await conflictService.detectConflicts(entity3);
|
|
144
|
+
console.log(`โ Found ${conflicts3.length} conflict(s)`);
|
|
145
|
+
if (conflicts3.length > 0) {
|
|
146
|
+
console.log(` Type: ${conflicts3[0].conflict_type}`);
|
|
147
|
+
console.log(` Confidence: ${(conflicts3[0].confidence * 100).toFixed(1)}%`);
|
|
148
|
+
console.log(` Reason: ${conflicts3[0].reason}`);
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
// Test 4: Conflict Resolution
|
|
152
|
+
console.log('Test 4: Conflict Resolution');
|
|
153
|
+
const entity4 = await createTestEntity(db, embeddings, 'Product Gamma');
|
|
154
|
+
await createTestObservation(db, embeddings, entity4, 'Product Gamma is available for purchase', oneMonthAgo);
|
|
155
|
+
await createTestObservation(db, embeddings, entity4, 'Product Gamma is no longer available and has been removed from catalog', now);
|
|
156
|
+
const resolution = await conflictService.resolveConflicts(entity4);
|
|
157
|
+
console.log(`โ Resolved ${resolution.resolved_conflicts} conflict(s)`);
|
|
158
|
+
console.log(` Invalidated observations: ${resolution.invalidated_observations.length}`);
|
|
159
|
+
console.log(` Audit observations created: ${resolution.audit_observations.length}`);
|
|
160
|
+
console.log('');
|
|
161
|
+
// Test 5: No Conflicts (Different Topics)
|
|
162
|
+
console.log('Test 5: No Conflicts (Different Topics)');
|
|
163
|
+
const entity5 = await createTestEntity(db, embeddings, 'Team Delta');
|
|
164
|
+
await createTestObservation(db, embeddings, entity5, 'Team Delta is working on the frontend', oneMonthAgo);
|
|
165
|
+
await createTestObservation(db, embeddings, entity5, 'Team Delta completed the backend integration', now);
|
|
166
|
+
const conflicts5 = await conflictService.detectConflicts(entity5);
|
|
167
|
+
console.log(`โ Found ${conflicts5.length} conflict(s) (expected: 0)`);
|
|
168
|
+
if (conflicts5.length > 0) {
|
|
169
|
+
console.log(` Unexpected conflict found:`);
|
|
170
|
+
console.log(` Type: ${conflicts5[0].conflict_type}`);
|
|
171
|
+
console.log(` Confidence: ${(conflicts5[0].confidence * 100).toFixed(1)}%`);
|
|
172
|
+
console.log(` Reason: ${conflicts5[0].reason}`);
|
|
173
|
+
}
|
|
174
|
+
console.log('');
|
|
175
|
+
// Test 6: Configuration Update
|
|
176
|
+
console.log('Test 6: Configuration Update');
|
|
177
|
+
const originalConfig = conflictService.getConfig();
|
|
178
|
+
console.log(` Original similarity threshold: ${originalConfig.similarityThreshold}`);
|
|
179
|
+
conflictService.updateConfig({ similarityThreshold: 0.9 });
|
|
180
|
+
const updatedConfig = conflictService.getConfig();
|
|
181
|
+
console.log(` Updated similarity threshold: ${updatedConfig.similarityThreshold}`);
|
|
182
|
+
console.log('โ Configuration updated successfully');
|
|
183
|
+
console.log('');
|
|
184
|
+
// Test 7: Time Window Filtering
|
|
185
|
+
console.log('Test 7: Time Window Filtering');
|
|
186
|
+
const entity7 = await createTestEntity(db, embeddings, 'Old Project');
|
|
187
|
+
const twoYearsAgo = now - (730 * 24 * 60 * 60 * 1000);
|
|
188
|
+
await createTestObservation(db, embeddings, entity7, 'Old Project is active', twoYearsAgo);
|
|
189
|
+
await createTestObservation(db, embeddings, entity7, 'Old Project is inactive', now);
|
|
190
|
+
// Should not detect conflict due to time window (default 365 days)
|
|
191
|
+
const conflicts7 = await conflictService.detectConflicts(entity7);
|
|
192
|
+
console.log(`โ Found ${conflicts7.length} conflict(s) (expected: 0 due to time window)`);
|
|
193
|
+
console.log('');
|
|
194
|
+
// Test 8: Multiple Conflicts
|
|
195
|
+
console.log('Test 8: Multiple Conflicts');
|
|
196
|
+
const entity8 = await createTestEntity(db, embeddings, 'Multi Conflict');
|
|
197
|
+
const threeMonthsAgo = now - (90 * 24 * 60 * 60 * 1000);
|
|
198
|
+
const twoMonthsAgo = now - (60 * 24 * 60 * 60 * 1000);
|
|
199
|
+
await createTestObservation(db, embeddings, entity8, 'Status is enabled and operational', threeMonthsAgo);
|
|
200
|
+
await createTestObservation(db, embeddings, entity8, 'Status is disabled temporarily', twoMonthsAgo);
|
|
201
|
+
await createTestObservation(db, embeddings, entity8, 'Status is permanently shut down', now);
|
|
202
|
+
const conflicts8 = await conflictService.detectConflicts(entity8);
|
|
203
|
+
console.log(`โ Found ${conflicts8.length} conflict(s)`);
|
|
204
|
+
conflicts8.forEach((c, i) => {
|
|
205
|
+
console.log(` Conflict ${i + 1}: ${c.conflict_type} (confidence: ${(c.confidence * 100).toFixed(1)}%)`);
|
|
206
|
+
});
|
|
207
|
+
console.log('');
|
|
208
|
+
console.log('โ
All tests completed successfully!');
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error('โ Test failed:', error);
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
// Cleanup
|
|
216
|
+
try {
|
|
217
|
+
const fs = await import('fs');
|
|
218
|
+
if (fs.existsSync(DB_PATH)) {
|
|
219
|
+
fs.unlinkSync(DB_PATH);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
// Ignore cleanup errors
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Run tests
|
|
228
|
+
runTests().catch(console.error);
|