cozo-memory 1.0.3 → 1.0.4
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 +246 -37
- package/dist/export-import-service.js +472 -0
- package/dist/index.js +242 -7
- package/dist/inference-engine.js +9 -2
- package/dist/test-bugfixes.js +374 -0
- package/dist/test-delete-comprehensive.js +174 -0
- package/dist/test-export-import.js +152 -0
- package/dist/test-fixes-simple.js +50 -0
- package/package.json +3 -1
- package/dist/verify_transaction_tool.js +0 -46
|
@@ -0,0 +1,472 @@
|
|
|
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
|
+
exports.ExportImportService = void 0;
|
|
7
|
+
const archiver_1 = __importDefault(require("archiver"));
|
|
8
|
+
class ExportImportService {
|
|
9
|
+
dbService;
|
|
10
|
+
constructor(dbService) {
|
|
11
|
+
this.dbService = dbService;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Export memory to various formats
|
|
15
|
+
*/
|
|
16
|
+
async exportMemory(options) {
|
|
17
|
+
console.error('[Export] Starting export with format:', options.format);
|
|
18
|
+
// Fetch all data
|
|
19
|
+
const entities = await this.fetchEntities(options);
|
|
20
|
+
const observations = options.includeObservations !== false
|
|
21
|
+
? await this.fetchObservations(options)
|
|
22
|
+
: [];
|
|
23
|
+
const relationships = options.includeRelationships !== false
|
|
24
|
+
? await this.fetchRelationships(options)
|
|
25
|
+
: [];
|
|
26
|
+
const stats = {
|
|
27
|
+
entities: entities.length,
|
|
28
|
+
observations: observations.length,
|
|
29
|
+
relationships: relationships.length,
|
|
30
|
+
};
|
|
31
|
+
console.error('[Export] Fetched data:', stats);
|
|
32
|
+
switch (options.format) {
|
|
33
|
+
case 'json':
|
|
34
|
+
return {
|
|
35
|
+
format: 'json',
|
|
36
|
+
data: this.exportToJSON(entities, observations, relationships, options),
|
|
37
|
+
stats,
|
|
38
|
+
};
|
|
39
|
+
case 'markdown':
|
|
40
|
+
return {
|
|
41
|
+
format: 'markdown',
|
|
42
|
+
data: this.exportToMarkdown(entities, observations, relationships, options),
|
|
43
|
+
stats,
|
|
44
|
+
};
|
|
45
|
+
case 'obsidian':
|
|
46
|
+
const zipBuffer = await this.exportToObsidianZip(entities, observations, relationships, options);
|
|
47
|
+
return {
|
|
48
|
+
format: 'obsidian',
|
|
49
|
+
zipBuffer,
|
|
50
|
+
stats,
|
|
51
|
+
};
|
|
52
|
+
default:
|
|
53
|
+
throw new Error(`Unsupported export format: ${options.format}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Import memory from various formats
|
|
58
|
+
*/
|
|
59
|
+
async importMemory(data, options) {
|
|
60
|
+
console.error('[Import] Starting import from format:', options.sourceFormat);
|
|
61
|
+
const result = {
|
|
62
|
+
imported: { entities: 0, observations: 0, relationships: 0 },
|
|
63
|
+
skipped: 0,
|
|
64
|
+
errors: [],
|
|
65
|
+
};
|
|
66
|
+
try {
|
|
67
|
+
switch (options.sourceFormat) {
|
|
68
|
+
case 'mem0':
|
|
69
|
+
return await this.importFromMem0(data, options, result);
|
|
70
|
+
case 'memgpt':
|
|
71
|
+
return await this.importFromMemGPT(data, options, result);
|
|
72
|
+
case 'markdown':
|
|
73
|
+
return await this.importFromMarkdown(data, options, result);
|
|
74
|
+
case 'cozo':
|
|
75
|
+
return await this.importFromCozoJSON(data, options, result);
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Unsupported import format: ${options.sourceFormat}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
result.errors.push(`Import failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// FETCH DATA
|
|
87
|
+
// ============================================================================
|
|
88
|
+
async fetchEntities(options) {
|
|
89
|
+
let query = `?[id, name, type, metadata, created_at] := *entity{id, name, type, metadata, created_at @ "NOW"}`;
|
|
90
|
+
if (options.entityTypes && options.entityTypes.length > 0) {
|
|
91
|
+
const typeFilter = options.entityTypes.map(t => `"${t}"`).join(', ');
|
|
92
|
+
query += `, type in [${typeFilter}]`;
|
|
93
|
+
}
|
|
94
|
+
if (options.since) {
|
|
95
|
+
query += `, created_at >= ${options.since}`;
|
|
96
|
+
}
|
|
97
|
+
const result = await this.dbService.run(query);
|
|
98
|
+
return result.rows || [];
|
|
99
|
+
}
|
|
100
|
+
async fetchObservations(options) {
|
|
101
|
+
let query = `?[id, entity_id, text, metadata, created_at] := *observation{id, entity_id, text, metadata, created_at @ "NOW"}`;
|
|
102
|
+
if (options.since) {
|
|
103
|
+
query += `, created_at >= ${options.since}`;
|
|
104
|
+
}
|
|
105
|
+
const result = await this.dbService.run(query);
|
|
106
|
+
return result.rows || [];
|
|
107
|
+
}
|
|
108
|
+
async fetchRelationships(options) {
|
|
109
|
+
let query = `?[from_id, to_id, relation_type, strength, metadata, created_at] := *relationship{from_id, to_id, relation_type, strength, metadata, created_at @ "NOW"}`;
|
|
110
|
+
if (options.since) {
|
|
111
|
+
query += `, created_at >= ${options.since}`;
|
|
112
|
+
}
|
|
113
|
+
const result = await this.dbService.run(query);
|
|
114
|
+
return result.rows || [];
|
|
115
|
+
}
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// EXPORT FORMATS
|
|
118
|
+
// ============================================================================
|
|
119
|
+
exportToJSON(entities, observations, relationships, options) {
|
|
120
|
+
return {
|
|
121
|
+
version: '1.0',
|
|
122
|
+
exported_at: new Date().toISOString(),
|
|
123
|
+
format: 'cozo-memory',
|
|
124
|
+
data: {
|
|
125
|
+
entities: entities.map(([id, name, type, metadata, created_at]) => ({
|
|
126
|
+
id,
|
|
127
|
+
name,
|
|
128
|
+
type,
|
|
129
|
+
metadata: options.includeMetadata !== false ? metadata : undefined,
|
|
130
|
+
created_at,
|
|
131
|
+
})),
|
|
132
|
+
observations: observations.map(([id, entity_id, text, metadata, created_at]) => ({
|
|
133
|
+
id,
|
|
134
|
+
entity_id,
|
|
135
|
+
text,
|
|
136
|
+
metadata: options.includeMetadata !== false ? metadata : undefined,
|
|
137
|
+
created_at,
|
|
138
|
+
})),
|
|
139
|
+
relationships: relationships.map(([from_id, to_id, relation_type, strength, metadata, created_at]) => ({
|
|
140
|
+
from_id,
|
|
141
|
+
to_id,
|
|
142
|
+
relation_type,
|
|
143
|
+
strength,
|
|
144
|
+
metadata: options.includeMetadata !== false ? metadata : undefined,
|
|
145
|
+
created_at,
|
|
146
|
+
})),
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
exportToMarkdown(entities, observations, relationships, options) {
|
|
151
|
+
let md = `# Memory Export\n\n`;
|
|
152
|
+
md += `Exported: ${new Date().toISOString()}\n\n`;
|
|
153
|
+
md += `## Statistics\n\n`;
|
|
154
|
+
md += `- Entities: ${entities.length}\n`;
|
|
155
|
+
md += `- Observations: ${observations.length}\n`;
|
|
156
|
+
md += `- Relationships: ${relationships.length}\n\n`;
|
|
157
|
+
md += `---\n\n`;
|
|
158
|
+
for (const [id, name, type, metadata, created_at] of entities) {
|
|
159
|
+
md += `## ${name}\n\n`;
|
|
160
|
+
md += `**Type:** ${type}\n\n`;
|
|
161
|
+
md += `**ID:** \`${id}\`\n\n`;
|
|
162
|
+
if (options.includeMetadata !== false && metadata && Object.keys(metadata).length > 0) {
|
|
163
|
+
md += `**Metadata:**\n\`\`\`json\n${JSON.stringify(metadata, null, 2)}\n\`\`\`\n\n`;
|
|
164
|
+
}
|
|
165
|
+
// Find observations for this entity
|
|
166
|
+
const entityObs = observations.filter(([, entity_id]) => entity_id === id);
|
|
167
|
+
if (entityObs.length > 0) {
|
|
168
|
+
md += `### Observations\n\n`;
|
|
169
|
+
for (const [obs_id, , text] of entityObs) {
|
|
170
|
+
md += `- ${text}\n`;
|
|
171
|
+
}
|
|
172
|
+
md += `\n`;
|
|
173
|
+
}
|
|
174
|
+
// Find relationships
|
|
175
|
+
const entityRels = relationships.filter(([from_id]) => from_id === id);
|
|
176
|
+
if (entityRels.length > 0) {
|
|
177
|
+
md += `### Relationships\n\n`;
|
|
178
|
+
for (const [, to_id, relation_type] of entityRels) {
|
|
179
|
+
const targetEntity = entities.find(([eid]) => eid === to_id);
|
|
180
|
+
const targetName = targetEntity ? targetEntity[1] : to_id;
|
|
181
|
+
md += `- **${relation_type}** → ${targetName}\n`;
|
|
182
|
+
}
|
|
183
|
+
md += `\n`;
|
|
184
|
+
}
|
|
185
|
+
md += `---\n\n`;
|
|
186
|
+
}
|
|
187
|
+
return md;
|
|
188
|
+
}
|
|
189
|
+
async exportToObsidianZip(entities, observations, relationships, options) {
|
|
190
|
+
return new Promise((resolve, reject) => {
|
|
191
|
+
const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
|
|
192
|
+
const chunks = [];
|
|
193
|
+
archive.on('data', (chunk) => chunks.push(chunk));
|
|
194
|
+
archive.on('end', () => resolve(Buffer.concat(chunks)));
|
|
195
|
+
archive.on('error', reject);
|
|
196
|
+
// Create README
|
|
197
|
+
archive.append(`# Memory Vault\n\nExported from CozoDB Memory on ${new Date().toISOString()}\n\n` +
|
|
198
|
+
`## Statistics\n\n- Entities: ${entities.length}\n- Observations: ${observations.length}\n- Relationships: ${relationships.length}\n`, { name: 'README.md' });
|
|
199
|
+
// Create entity notes
|
|
200
|
+
for (const [id, name, type, metadata, created_at] of entities) {
|
|
201
|
+
const safeName = this.sanitizeFilename(name);
|
|
202
|
+
let content = `---\n`;
|
|
203
|
+
content += `id: ${id}\n`;
|
|
204
|
+
content += `type: ${type}\n`;
|
|
205
|
+
// CozoDB timestamps are in microseconds, convert to milliseconds for Date
|
|
206
|
+
const timestamp = typeof created_at === 'number' ? created_at / 1000 : Date.now();
|
|
207
|
+
content += `created: ${new Date(timestamp).toISOString()}\n`;
|
|
208
|
+
if (options.includeMetadata !== false && metadata && Object.keys(metadata).length > 0) {
|
|
209
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
210
|
+
content += `${key}: ${JSON.stringify(value)}\n`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
content += `---\n\n`;
|
|
214
|
+
content += `# ${name}\n\n`;
|
|
215
|
+
// Add observations
|
|
216
|
+
const entityObs = observations.filter(([, entity_id]) => entity_id === id);
|
|
217
|
+
if (entityObs.length > 0) {
|
|
218
|
+
content += `## Notes\n\n`;
|
|
219
|
+
for (const [, , text] of entityObs) {
|
|
220
|
+
content += `- ${text}\n`;
|
|
221
|
+
}
|
|
222
|
+
content += `\n`;
|
|
223
|
+
}
|
|
224
|
+
// Add relationships with wiki-links
|
|
225
|
+
const outgoing = relationships.filter(([from_id]) => from_id === id);
|
|
226
|
+
const incoming = relationships.filter(([, to_id]) => to_id === id);
|
|
227
|
+
if (outgoing.length > 0) {
|
|
228
|
+
content += `## Connections\n\n`;
|
|
229
|
+
for (const [, to_id, relation_type] of outgoing) {
|
|
230
|
+
const targetEntity = entities.find(([eid]) => eid === to_id);
|
|
231
|
+
if (targetEntity) {
|
|
232
|
+
const targetName = this.sanitizeFilename(targetEntity[1]);
|
|
233
|
+
content += `- **${relation_type}**: [[${targetName}]]\n`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
content += `\n`;
|
|
237
|
+
}
|
|
238
|
+
if (incoming.length > 0) {
|
|
239
|
+
content += `## Referenced By\n\n`;
|
|
240
|
+
for (const [from_id, , relation_type] of incoming) {
|
|
241
|
+
const sourceEntity = entities.find(([eid]) => eid === from_id);
|
|
242
|
+
if (sourceEntity) {
|
|
243
|
+
const sourceName = this.sanitizeFilename(sourceEntity[1]);
|
|
244
|
+
content += `- [[${sourceName}]] (**${relation_type}**)\n`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
content += `\n`;
|
|
248
|
+
}
|
|
249
|
+
archive.append(content, { name: `${safeName}.md` });
|
|
250
|
+
}
|
|
251
|
+
archive.finalize();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
// ============================================================================
|
|
255
|
+
// IMPORT FORMATS
|
|
256
|
+
// ============================================================================
|
|
257
|
+
async importFromMem0(data, options, result) {
|
|
258
|
+
const memories = typeof data === 'string' ? JSON.parse(data) : data;
|
|
259
|
+
const memoryArray = Array.isArray(memories) ? memories : [memories];
|
|
260
|
+
for (const mem of memoryArray) {
|
|
261
|
+
try {
|
|
262
|
+
// Mem0 format: { id, memory, user_id, metadata, created_at }
|
|
263
|
+
const entityName = mem.user_id || 'Imported User';
|
|
264
|
+
const entityType = options.defaultEntityType || 'Person';
|
|
265
|
+
// Check if entity exists
|
|
266
|
+
const existingEntity = await this.findEntityByName(entityName);
|
|
267
|
+
let entityId;
|
|
268
|
+
if (existingEntity) {
|
|
269
|
+
entityId = existingEntity;
|
|
270
|
+
if (options.mergeStrategy === 'skip') {
|
|
271
|
+
result.skipped++;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// Create entity
|
|
277
|
+
entityId = await this.createEntity(entityName, entityType, mem.metadata || {});
|
|
278
|
+
result.imported.entities++;
|
|
279
|
+
}
|
|
280
|
+
// Add observation
|
|
281
|
+
await this.createObservation(entityId, mem.memory, mem.metadata || {});
|
|
282
|
+
result.imported.observations++;
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
result.errors.push(`Failed to import Mem0 entry: ${error instanceof Error ? error.message : String(error)}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
async importFromMemGPT(data, options, result) {
|
|
291
|
+
const memgptData = typeof data === 'string' ? JSON.parse(data) : data;
|
|
292
|
+
// MemGPT has archival_memory and recall_memory
|
|
293
|
+
const archival = memgptData.archival_memory || [];
|
|
294
|
+
const recall = memgptData.recall_memory || [];
|
|
295
|
+
// Create MemGPT agent entity
|
|
296
|
+
const agentName = memgptData.agent_name || 'MemGPT Agent';
|
|
297
|
+
const entityId = await this.createEntity(agentName, 'Agent', { source: 'memgpt' });
|
|
298
|
+
result.imported.entities++;
|
|
299
|
+
// Import archival memory
|
|
300
|
+
for (const item of archival) {
|
|
301
|
+
try {
|
|
302
|
+
await this.createObservation(entityId, item.content || item.text || item, {
|
|
303
|
+
type: 'archival',
|
|
304
|
+
timestamp: item.timestamp
|
|
305
|
+
});
|
|
306
|
+
result.imported.observations++;
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
result.errors.push(`Failed to import MemGPT archival: ${error instanceof Error ? error.message : String(error)}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Import recall memory
|
|
313
|
+
for (const item of recall) {
|
|
314
|
+
try {
|
|
315
|
+
await this.createObservation(entityId, item.content || item.text || item, {
|
|
316
|
+
type: 'recall',
|
|
317
|
+
timestamp: item.timestamp
|
|
318
|
+
});
|
|
319
|
+
result.imported.observations++;
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
result.errors.push(`Failed to import MemGPT recall: ${error instanceof Error ? error.message : String(error)}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
async importFromMarkdown(data, options, result) {
|
|
328
|
+
// Simple markdown parser: split by ## headers
|
|
329
|
+
const sections = data.split(/^## /m).filter(s => s.trim());
|
|
330
|
+
for (const section of sections) {
|
|
331
|
+
try {
|
|
332
|
+
const lines = section.split('\n');
|
|
333
|
+
const name = lines[0].trim();
|
|
334
|
+
if (!name || name === 'Statistics')
|
|
335
|
+
continue;
|
|
336
|
+
const entityType = options.defaultEntityType || 'Note';
|
|
337
|
+
const entityId = await this.createEntity(name, entityType, { source: 'markdown' });
|
|
338
|
+
result.imported.entities++;
|
|
339
|
+
// Extract observations (lines starting with -)
|
|
340
|
+
const observations = lines.filter(l => l.trim().startsWith('-')).map(l => l.trim().substring(1).trim());
|
|
341
|
+
for (const obs of observations) {
|
|
342
|
+
if (obs) {
|
|
343
|
+
await this.createObservation(entityId, obs, {});
|
|
344
|
+
result.imported.observations++;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
result.errors.push(`Failed to import markdown section: ${error instanceof Error ? error.message : String(error)}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
async importFromCozoJSON(data, options, result) {
|
|
355
|
+
const cozoData = typeof data === 'string' ? JSON.parse(data) : data;
|
|
356
|
+
if (!cozoData.data) {
|
|
357
|
+
throw new Error('Invalid Cozo export format');
|
|
358
|
+
}
|
|
359
|
+
const { entities, observations, relationships } = cozoData.data;
|
|
360
|
+
// Import entities
|
|
361
|
+
for (const entity of entities || []) {
|
|
362
|
+
try {
|
|
363
|
+
if (options.mergeStrategy === 'skip') {
|
|
364
|
+
const existing = await this.findEntityById(entity.id);
|
|
365
|
+
if (existing) {
|
|
366
|
+
result.skipped++;
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
await this.createEntityWithId(entity.id, entity.name, entity.type, entity.metadata || {});
|
|
371
|
+
result.imported.entities++;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
result.errors.push(`Failed to import entity ${entity.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// Import observations
|
|
378
|
+
for (const obs of observations || []) {
|
|
379
|
+
try {
|
|
380
|
+
await this.createObservationWithId(obs.id, obs.entity_id, obs.text, obs.metadata || {});
|
|
381
|
+
result.imported.observations++;
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
result.errors.push(`Failed to import observation: ${error instanceof Error ? error.message : String(error)}`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// Import relationships
|
|
388
|
+
for (const rel of relationships || []) {
|
|
389
|
+
try {
|
|
390
|
+
await this.createRelationship(rel.from_id, rel.to_id, rel.relation_type, rel.strength || 1.0, rel.metadata || {});
|
|
391
|
+
result.imported.relationships++;
|
|
392
|
+
}
|
|
393
|
+
catch (error) {
|
|
394
|
+
result.errors.push(`Failed to import relationship: ${error instanceof Error ? error.message : String(error)}`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// HELPER METHODS
|
|
401
|
+
// ============================================================================
|
|
402
|
+
sanitizeFilename(name) {
|
|
403
|
+
return name.replace(/[<>:"/\\|?*]/g, '-').replace(/\s+/g, ' ').trim();
|
|
404
|
+
}
|
|
405
|
+
async findEntityByName(name) {
|
|
406
|
+
const result = await this.dbService.run(`?[id] := *entity{id, name @ "NOW"}, name == "${name}"`);
|
|
407
|
+
return result.rows && result.rows.length > 0 ? result.rows[0][0] : null;
|
|
408
|
+
}
|
|
409
|
+
async findEntityById(id) {
|
|
410
|
+
const result = await this.dbService.run(`?[id] := *entity{id @ "NOW"}, id == "${id}"`);
|
|
411
|
+
return result.rows && result.rows.length > 0;
|
|
412
|
+
}
|
|
413
|
+
async createEntity(name, type, metadata) {
|
|
414
|
+
const { v4: uuidv4 } = await import('uuid');
|
|
415
|
+
const id = uuidv4();
|
|
416
|
+
await this.createEntityWithId(id, name, type, metadata);
|
|
417
|
+
return id;
|
|
418
|
+
}
|
|
419
|
+
async createEntityWithId(id, name, type, metadata) {
|
|
420
|
+
const now = Date.now() * 1000;
|
|
421
|
+
const zeroVec = new Array(1024).fill(0);
|
|
422
|
+
// Escape strings properly for CozoDB
|
|
423
|
+
const escapedName = name.replace(/"/g, '\\"');
|
|
424
|
+
const escapedType = type.replace(/"/g, '\\"');
|
|
425
|
+
await this.dbService.run(`
|
|
426
|
+
?[id, name, type, embedding, name_embedding, metadata, created_at] <- [[$id, $name, $type, $embedding, $name_embedding, $metadata, [${now}, true]]]
|
|
427
|
+
:insert entity {id, name, type, embedding, name_embedding, metadata, created_at}
|
|
428
|
+
`, {
|
|
429
|
+
id,
|
|
430
|
+
name: escapedName,
|
|
431
|
+
type: escapedType,
|
|
432
|
+
embedding: zeroVec,
|
|
433
|
+
name_embedding: zeroVec,
|
|
434
|
+
metadata: metadata || {}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
async createObservation(entityId, text, metadata) {
|
|
438
|
+
const { v4: uuidv4 } = await import('uuid');
|
|
439
|
+
const id = uuidv4();
|
|
440
|
+
await this.createObservationWithId(id, entityId, text, metadata);
|
|
441
|
+
return id;
|
|
442
|
+
}
|
|
443
|
+
async createObservationWithId(id, entityId, text, metadata) {
|
|
444
|
+
const now = Date.now() * 1000;
|
|
445
|
+
const zeroVec = new Array(1024).fill(0);
|
|
446
|
+
const escapedText = text.replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
447
|
+
await this.dbService.run(`
|
|
448
|
+
?[id, entity_id, text, embedding, metadata, created_at] <- [[$id, $entity_id, $text, $embedding, $metadata, [${now}, true]]]
|
|
449
|
+
:insert observation {id, entity_id, text, embedding, metadata, created_at}
|
|
450
|
+
`, {
|
|
451
|
+
id,
|
|
452
|
+
entity_id: entityId,
|
|
453
|
+
text: escapedText,
|
|
454
|
+
embedding: zeroVec,
|
|
455
|
+
metadata: metadata || {}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
async createRelationship(fromId, toId, relationType, strength, metadata) {
|
|
459
|
+
const now = Date.now() * 1000;
|
|
460
|
+
await this.dbService.run(`
|
|
461
|
+
?[from_id, to_id, relation_type, strength, metadata, created_at] <- [[$from_id, $to_id, $relation_type, $strength, $metadata, [${now}, true]]]
|
|
462
|
+
:insert relationship {from_id, to_id, relation_type, strength, metadata, created_at}
|
|
463
|
+
`, {
|
|
464
|
+
from_id: fromId,
|
|
465
|
+
to_id: toId,
|
|
466
|
+
relation_type: relationType,
|
|
467
|
+
strength,
|
|
468
|
+
metadata: metadata || {}
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
exports.ExportImportService = ExportImportService;
|