agent-memory-graph 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/config/default.json +28 -0
  4. package/config/graph.config.json +28 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +303 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/plugin/entry.d.ts +3 -0
  10. package/dist/plugin/entry.d.ts.map +1 -0
  11. package/dist/plugin/entry.js +1652 -0
  12. package/dist/plugin/entry.js.map +1 -0
  13. package/dist/src/config/defaults.d.ts +8 -0
  14. package/dist/src/config/defaults.d.ts.map +1 -0
  15. package/dist/src/config/defaults.js +31 -0
  16. package/dist/src/config/defaults.js.map +1 -0
  17. package/dist/src/config/schema.d.ts +162 -0
  18. package/dist/src/config/schema.d.ts.map +1 -0
  19. package/dist/src/config/schema.js +39 -0
  20. package/dist/src/config/schema.js.map +1 -0
  21. package/dist/src/extract/dedup.d.ts +14 -0
  22. package/dist/src/extract/dedup.d.ts.map +1 -0
  23. package/dist/src/extract/dedup.js +79 -0
  24. package/dist/src/extract/dedup.js.map +1 -0
  25. package/dist/src/extract/extractor.d.ts +24 -0
  26. package/dist/src/extract/extractor.d.ts.map +1 -0
  27. package/dist/src/extract/extractor.js +162 -0
  28. package/dist/src/extract/extractor.js.map +1 -0
  29. package/dist/src/graph/engine.d.ts +90 -0
  30. package/dist/src/graph/engine.d.ts.map +1 -0
  31. package/dist/src/graph/engine.js +307 -0
  32. package/dist/src/graph/engine.js.map +1 -0
  33. package/dist/src/graph/schema.d.ts +12 -0
  34. package/dist/src/graph/schema.d.ts.map +1 -0
  35. package/dist/src/graph/schema.js +115 -0
  36. package/dist/src/graph/schema.js.map +1 -0
  37. package/dist/src/index.d.ts +129 -0
  38. package/dist/src/index.d.ts.map +1 -0
  39. package/dist/src/index.js +174 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/search/hybrid.d.ts +22 -0
  42. package/dist/src/search/hybrid.d.ts.map +1 -0
  43. package/dist/src/search/hybrid.js +38 -0
  44. package/dist/src/search/hybrid.js.map +1 -0
  45. package/dist/src/search/natural-language.d.ts +20 -0
  46. package/dist/src/search/natural-language.d.ts.map +1 -0
  47. package/dist/src/search/natural-language.js +429 -0
  48. package/dist/src/search/natural-language.js.map +1 -0
  49. package/dist/src/sync/export.d.ts +12 -0
  50. package/dist/src/sync/export.d.ts.map +1 -0
  51. package/dist/src/sync/export.js +117 -0
  52. package/dist/src/sync/export.js.map +1 -0
  53. package/dist/src/sync/memory-md.d.ts +19 -0
  54. package/dist/src/sync/memory-md.d.ts.map +1 -0
  55. package/dist/src/sync/memory-md.js +78 -0
  56. package/dist/src/sync/memory-md.js.map +1 -0
  57. package/openclaw.plugin.json +55 -0
  58. package/package.json +90 -0
@@ -0,0 +1,90 @@
1
+ export interface Entity {
2
+ id: string;
3
+ name: string;
4
+ type: string;
5
+ properties: Record<string, unknown>;
6
+ created_at: string;
7
+ updated_at: string;
8
+ source?: string;
9
+ confidence: number;
10
+ }
11
+ export interface Relationship {
12
+ id: string;
13
+ from_id: string;
14
+ to_id: string;
15
+ relation: string;
16
+ properties: Record<string, unknown>;
17
+ created_at: string;
18
+ updated_at: string;
19
+ source?: string;
20
+ confidence: number;
21
+ }
22
+ export interface GraphStats {
23
+ entities: number;
24
+ relationships: number;
25
+ entityTypes: string[];
26
+ relationTypes: string[];
27
+ oldestEntry: string | null;
28
+ newestEntry: string | null;
29
+ }
30
+ export declare class GraphEngine {
31
+ private db;
32
+ constructor(dbPath: string);
33
+ addEntity(name: string, type: string, properties?: Record<string, unknown>, options?: {
34
+ source?: string;
35
+ confidence?: number;
36
+ }): Entity;
37
+ getEntity(id: string): Entity | null;
38
+ findEntityByName(name: string, type?: string): Entity | null;
39
+ updateEntity(id: string, updates: {
40
+ name?: string;
41
+ type?: string;
42
+ properties?: Record<string, unknown>;
43
+ source?: string;
44
+ confidence?: number;
45
+ }): Entity;
46
+ deleteEntity(id: string): boolean;
47
+ listEntities(options?: {
48
+ type?: string;
49
+ limit?: number;
50
+ offset?: number;
51
+ }): Entity[];
52
+ addRelation(fromName: string, relation: string, toName: string, options?: {
53
+ properties?: Record<string, unknown>;
54
+ source?: string;
55
+ confidence?: number;
56
+ fromType?: string;
57
+ toType?: string;
58
+ }): Relationship;
59
+ getRelationsFrom(entityId: string): (Relationship & {
60
+ to_name: string;
61
+ to_type: string;
62
+ })[];
63
+ getRelationsTo(entityId: string): (Relationship & {
64
+ from_name: string;
65
+ from_type: string;
66
+ })[];
67
+ deleteRelation(id: string): boolean;
68
+ searchEntities(query: string, limit?: number): Entity[];
69
+ /**
70
+ * Find path between two entities (BFS, max depth)
71
+ */
72
+ findPath(fromName: string, toName: string, maxHops?: number): {
73
+ path: string[];
74
+ relations: string[];
75
+ } | null;
76
+ /**
77
+ * Get neighborhood of an entity (all connected within N hops)
78
+ */
79
+ getNeighborhood(entityName: string, hops?: number): {
80
+ entities: Entity[];
81
+ relationships: Relationship[];
82
+ };
83
+ stats(): GraphStats;
84
+ logExtraction(rawText: string, entities: any[], relations: any[], sessionId?: string): void;
85
+ private rowToEntity;
86
+ private rowToRelationship;
87
+ /** Close database */
88
+ close(): void;
89
+ }
90
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/graph/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,307 @@
1
+ import { nanoid } from 'nanoid';
2
+ import { SchemaManager } from './schema.js';
3
+ export class GraphEngine {
4
+ db;
5
+ constructor(dbPath) {
6
+ const schema = new SchemaManager(dbPath);
7
+ this.db = schema.initialize();
8
+ }
9
+ // ─── Entity CRUD ───────────────────────────────────────────────
10
+ addEntity(name, type, properties = {}, options = {}) {
11
+ const existing = this.findEntityByName(name, type);
12
+ if (existing) {
13
+ // Update existing entity
14
+ return this.updateEntity(existing.id, { properties, ...options });
15
+ }
16
+ const id = `e-${nanoid(12)}`;
17
+ const now = new Date().toISOString();
18
+ this.db.prepare(`
19
+ INSERT INTO entities (id, name, type, properties, created_at, updated_at, source, confidence)
20
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
21
+ `).run(id, name, type, JSON.stringify(properties), now, now, options.source ?? null, options.confidence ?? 1.0);
22
+ return { id, name, type, properties, created_at: now, updated_at: now, source: options.source, confidence: options.confidence ?? 1.0 };
23
+ }
24
+ getEntity(id) {
25
+ const row = this.db.prepare(`SELECT * FROM entities WHERE id = ?`).get(id);
26
+ return row ? this.rowToEntity(row) : null;
27
+ }
28
+ findEntityByName(name, type) {
29
+ const query = type
30
+ ? `SELECT * FROM entities WHERE name = ? COLLATE NOCASE AND type = ? COLLATE NOCASE LIMIT 1`
31
+ : `SELECT * FROM entities WHERE name = ? COLLATE NOCASE LIMIT 1`;
32
+ const row = type
33
+ ? this.db.prepare(query).get(name, type)
34
+ : this.db.prepare(query).get(name);
35
+ return row ? this.rowToEntity(row) : null;
36
+ }
37
+ updateEntity(id, updates) {
38
+ const existing = this.getEntity(id);
39
+ if (!existing)
40
+ throw new Error(`Entity ${id} not found`);
41
+ const merged = {
42
+ name: updates.name ?? existing.name,
43
+ type: updates.type ?? existing.type,
44
+ properties: updates.properties ? { ...existing.properties, ...updates.properties } : existing.properties,
45
+ source: updates.source ?? existing.source,
46
+ confidence: updates.confidence ?? existing.confidence,
47
+ };
48
+ const now = new Date().toISOString();
49
+ this.db.prepare(`
50
+ UPDATE entities SET name = ?, type = ?, properties = ?, source = ?, confidence = ?, updated_at = ?
51
+ WHERE id = ?
52
+ `).run(merged.name, merged.type, JSON.stringify(merged.properties), merged.source ?? null, merged.confidence, now, id);
53
+ return { ...existing, ...merged, updated_at: now };
54
+ }
55
+ deleteEntity(id) {
56
+ const result = this.db.prepare(`DELETE FROM entities WHERE id = ?`).run(id);
57
+ return result.changes > 0;
58
+ }
59
+ listEntities(options = {}) {
60
+ const { type, limit = 100, offset = 0 } = options;
61
+ const query = type
62
+ ? `SELECT * FROM entities WHERE type = ? COLLATE NOCASE ORDER BY updated_at DESC LIMIT ? OFFSET ?`
63
+ : `SELECT * FROM entities ORDER BY updated_at DESC LIMIT ? OFFSET ?`;
64
+ const rows = type
65
+ ? this.db.prepare(query).all(type, limit, offset)
66
+ : this.db.prepare(query).all(limit, offset);
67
+ return rows.map(r => this.rowToEntity(r));
68
+ }
69
+ // ─── Relationship CRUD ─────────────────────────────────────────
70
+ addRelation(fromName, relation, toName, options = {}) {
71
+ // Resolve entities by name (create if not exist)
72
+ let fromEntity = this.findEntityByName(fromName);
73
+ if (!fromEntity) {
74
+ fromEntity = this.addEntity(fromName, options.fromType ?? 'Unknown', {}, { source: options.source });
75
+ }
76
+ let toEntity = this.findEntityByName(toName);
77
+ if (!toEntity) {
78
+ toEntity = this.addEntity(toName, options.toType ?? 'Unknown', {}, { source: options.source });
79
+ }
80
+ // Check for existing relationship
81
+ const existing = this.db.prepare(`
82
+ SELECT * FROM relationships WHERE from_id = ? AND to_id = ? AND relation = ? COLLATE NOCASE LIMIT 1
83
+ `).get(fromEntity.id, toEntity.id, relation);
84
+ if (existing) {
85
+ // Update confidence/properties
86
+ const now = new Date().toISOString();
87
+ const mergedProps = { ...JSON.parse(existing.properties || '{}'), ...(options.properties ?? {}) };
88
+ this.db.prepare(`
89
+ UPDATE relationships SET properties = ?, confidence = ?, updated_at = ? WHERE id = ?
90
+ `).run(JSON.stringify(mergedProps), options.confidence ?? existing.confidence, now, existing.id);
91
+ return this.rowToRelationship({ ...existing, properties: JSON.stringify(mergedProps), updated_at: now });
92
+ }
93
+ const id = `r-${nanoid(12)}`;
94
+ const now = new Date().toISOString();
95
+ this.db.prepare(`
96
+ INSERT INTO relationships (id, from_id, to_id, relation, properties, created_at, updated_at, source, confidence)
97
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
98
+ `).run(id, fromEntity.id, toEntity.id, relation, JSON.stringify(options.properties ?? {}), now, now, options.source ?? null, options.confidence ?? 1.0);
99
+ return {
100
+ id, from_id: fromEntity.id, to_id: toEntity.id, relation,
101
+ properties: options.properties ?? {}, created_at: now, updated_at: now,
102
+ source: options.source, confidence: options.confidence ?? 1.0
103
+ };
104
+ }
105
+ getRelationsFrom(entityId) {
106
+ const rows = this.db.prepare(`
107
+ SELECT r.*, e.name as to_name, e.type as to_type
108
+ FROM relationships r
109
+ JOIN entities e ON r.to_id = e.id
110
+ WHERE r.from_id = ?
111
+ ORDER BY r.updated_at DESC
112
+ `).all(entityId);
113
+ return rows.map(r => ({ ...this.rowToRelationship(r), to_name: r.to_name, to_type: r.to_type }));
114
+ }
115
+ getRelationsTo(entityId) {
116
+ const rows = this.db.prepare(`
117
+ SELECT r.*, e.name as from_name, e.type as from_type
118
+ FROM relationships r
119
+ JOIN entities e ON r.from_id = e.id
120
+ WHERE r.to_id = ?
121
+ ORDER BY r.updated_at DESC
122
+ `).all(entityId);
123
+ return rows.map(r => ({ ...this.rowToRelationship(r), from_name: r.from_name, from_type: r.from_type }));
124
+ }
125
+ deleteRelation(id) {
126
+ const result = this.db.prepare(`DELETE FROM relationships WHERE id = ?`).run(id);
127
+ return result.changes > 0;
128
+ }
129
+ // ─── Search ────────────────────────────────────────────────────
130
+ searchEntities(query, limit = 10) {
131
+ // Sanitize query for FTS5 (remove special characters)
132
+ const sanitized = query.replace(/[?!@#$%^&*(){}\[\]<>:;"'`~|/\\+=]/g, ' ').trim();
133
+ if (sanitized.length > 0) {
134
+ // Try FTS first
135
+ try {
136
+ const ftsRows = this.db.prepare(`
137
+ SELECT e.* FROM entities_fts fts
138
+ JOIN entities e ON e.rowid = fts.rowid
139
+ WHERE entities_fts MATCH ?
140
+ LIMIT ?
141
+ `).all(sanitized, limit);
142
+ if (ftsRows.length > 0) {
143
+ return ftsRows.map(r => this.rowToEntity(r));
144
+ }
145
+ }
146
+ catch {
147
+ // FTS query failed, fall through to LIKE
148
+ }
149
+ }
150
+ // Fallback to LIKE search
151
+ const likeQuery = sanitized.length > 0 ? sanitized : query;
152
+ const likeRows = this.db.prepare(`
153
+ SELECT * FROM entities
154
+ WHERE name LIKE ? COLLATE NOCASE OR type LIKE ? COLLATE NOCASE
155
+ LIMIT ?
156
+ `).all(`%${likeQuery}%`, `%${likeQuery}%`, limit);
157
+ return likeRows.map(r => this.rowToEntity(r));
158
+ }
159
+ // ─── Graph Traversal ───────────────────────────────────────────
160
+ /**
161
+ * Find path between two entities (BFS, max depth)
162
+ */
163
+ findPath(fromName, toName, maxHops = 3) {
164
+ const fromEntity = this.findEntityByName(fromName);
165
+ const toEntity = this.findEntityByName(toName);
166
+ if (!fromEntity || !toEntity)
167
+ return null;
168
+ // BFS
169
+ const queue = [
170
+ { entityId: fromEntity.id, path: [fromEntity.name], relations: [] }
171
+ ];
172
+ const visited = new Set([fromEntity.id]);
173
+ while (queue.length > 0) {
174
+ const current = queue.shift();
175
+ if (current.path.length > maxHops + 1)
176
+ break;
177
+ // Get all neighbors (both directions)
178
+ const outgoing = this.db.prepare(`
179
+ SELECT r.relation, r.to_id as neighbor_id, e.name as neighbor_name
180
+ FROM relationships r JOIN entities e ON r.to_id = e.id
181
+ WHERE r.from_id = ?
182
+ `).all(current.entityId);
183
+ const incoming = this.db.prepare(`
184
+ SELECT r.relation, r.from_id as neighbor_id, e.name as neighbor_name
185
+ FROM relationships r JOIN entities e ON r.from_id = e.id
186
+ WHERE r.to_id = ?
187
+ `).all(current.entityId);
188
+ const neighbors = [
189
+ ...outgoing.map((n) => ({ ...n, direction: '->' })),
190
+ ...incoming.map((n) => ({ ...n, direction: '<-' })),
191
+ ];
192
+ for (const neighbor of neighbors) {
193
+ if (neighbor.neighbor_id === toEntity.id) {
194
+ return {
195
+ path: [...current.path, neighbor.neighbor_name],
196
+ relations: [...current.relations, `${neighbor.direction}[${neighbor.relation}]`],
197
+ };
198
+ }
199
+ if (!visited.has(neighbor.neighbor_id)) {
200
+ visited.add(neighbor.neighbor_id);
201
+ queue.push({
202
+ entityId: neighbor.neighbor_id,
203
+ path: [...current.path, neighbor.neighbor_name],
204
+ relations: [...current.relations, `${neighbor.direction}[${neighbor.relation}]`],
205
+ });
206
+ }
207
+ }
208
+ }
209
+ return null;
210
+ }
211
+ /**
212
+ * Get neighborhood of an entity (all connected within N hops)
213
+ */
214
+ getNeighborhood(entityName, hops = 1) {
215
+ const entity = this.findEntityByName(entityName);
216
+ if (!entity)
217
+ return { entities: [], relationships: [] };
218
+ const entityIds = new Set([entity.id]);
219
+ const relIds = new Set();
220
+ let frontier = [entity.id];
221
+ for (let i = 0; i < hops; i++) {
222
+ const nextFrontier = [];
223
+ for (const nodeId of frontier) {
224
+ const rels = this.db.prepare(`
225
+ SELECT * FROM relationships WHERE from_id = ? OR to_id = ?
226
+ `).all(nodeId, nodeId);
227
+ for (const rel of rels) {
228
+ relIds.add(rel.id);
229
+ const neighborId = rel.from_id === nodeId ? rel.to_id : rel.from_id;
230
+ if (!entityIds.has(neighborId)) {
231
+ entityIds.add(neighborId);
232
+ nextFrontier.push(neighborId);
233
+ }
234
+ }
235
+ }
236
+ frontier = nextFrontier;
237
+ }
238
+ const entities = [...entityIds]
239
+ .map(id => this.getEntity(id))
240
+ .filter((e) => e !== null);
241
+ const relationships = [...relIds]
242
+ .map(id => {
243
+ const row = this.db.prepare(`SELECT * FROM relationships WHERE id = ?`).get(id);
244
+ return row ? this.rowToRelationship(row) : null;
245
+ })
246
+ .filter((r) => r !== null);
247
+ return { entities, relationships };
248
+ }
249
+ // ─── Stats ─────────────────────────────────────────────────────
250
+ stats() {
251
+ const entityCount = this.db.prepare(`SELECT COUNT(*) as c FROM entities`).get().c;
252
+ const relCount = this.db.prepare(`SELECT COUNT(*) as c FROM relationships`).get().c;
253
+ const entityTypes = this.db.prepare(`SELECT DISTINCT type FROM entities ORDER BY type`).all()
254
+ .map(r => r.type);
255
+ const relationTypes = this.db.prepare(`SELECT DISTINCT relation FROM relationships ORDER BY relation`).all()
256
+ .map(r => r.relation);
257
+ const oldest = this.db.prepare(`SELECT MIN(created_at) as t FROM entities`).get();
258
+ const newest = this.db.prepare(`SELECT MAX(updated_at) as t FROM entities`).get();
259
+ return {
260
+ entities: entityCount,
261
+ relationships: relCount,
262
+ entityTypes,
263
+ relationTypes,
264
+ oldestEntry: oldest?.t ?? null,
265
+ newestEntry: newest?.t ?? null,
266
+ };
267
+ }
268
+ // ─── Memory Log ────────────────────────────────────────────────
269
+ logExtraction(rawText, entities, relations, sessionId) {
270
+ const id = `log-${nanoid(12)}`;
271
+ this.db.prepare(`
272
+ INSERT INTO memory_log (id, raw_text, extracted_entities, extracted_relations, session_id)
273
+ VALUES (?, ?, ?, ?, ?)
274
+ `).run(id, rawText, JSON.stringify(entities), JSON.stringify(relations), sessionId ?? null);
275
+ }
276
+ // ─── Helpers ───────────────────────────────────────────────────
277
+ rowToEntity(row) {
278
+ return {
279
+ id: row.id,
280
+ name: row.name,
281
+ type: row.type,
282
+ properties: JSON.parse(row.properties || '{}'),
283
+ created_at: row.created_at,
284
+ updated_at: row.updated_at,
285
+ source: row.source ?? undefined,
286
+ confidence: row.confidence,
287
+ };
288
+ }
289
+ rowToRelationship(row) {
290
+ return {
291
+ id: row.id,
292
+ from_id: row.from_id,
293
+ to_id: row.to_id,
294
+ relation: row.relation,
295
+ properties: JSON.parse(row.properties || '{}'),
296
+ created_at: row.created_at,
297
+ updated_at: row.updated_at,
298
+ source: row.source ?? undefined,
299
+ confidence: row.confidence,
300
+ };
301
+ }
302
+ /** Close database */
303
+ close() {
304
+ this.db.close();
305
+ }
306
+ }
307
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/graph/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import Database from 'better-sqlite3';
2
+ export declare class SchemaManager {
3
+ private db;
4
+ constructor(dbPath: string);
5
+ /** Initialize schema (idempotent) */
6
+ initialize(): Database.Database;
7
+ /** Get current schema version */
8
+ getVersion(): number;
9
+ /** Close database connection */
10
+ close(): void;
11
+ }
12
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/graph/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAoFtC,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAU1B,qCAAqC;IACrC,UAAU,IAAI,QAAQ,CAAC,QAAQ;IAY/B,iCAAiC;IACjC,UAAU,IAAI,MAAM;IAWpB,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,115 @@
1
+ import Database from 'better-sqlite3';
2
+ import { resolve } from 'node:path';
3
+ import { mkdirSync } from 'node:fs';
4
+ const SCHEMA_VERSION = 1;
5
+ const SCHEMA_SQL = `
6
+ -- Schema version tracking
7
+ CREATE TABLE IF NOT EXISTS _meta (
8
+ key TEXT PRIMARY KEY,
9
+ value TEXT
10
+ );
11
+
12
+ -- Entities (graph nodes)
13
+ CREATE TABLE IF NOT EXISTS entities (
14
+ id TEXT PRIMARY KEY,
15
+ name TEXT NOT NULL,
16
+ type TEXT NOT NULL,
17
+ properties TEXT DEFAULT '{}',
18
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
19
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
20
+ source TEXT,
21
+ confidence REAL DEFAULT 1.0
22
+ );
23
+
24
+ -- Relationships (graph edges)
25
+ CREATE TABLE IF NOT EXISTS relationships (
26
+ id TEXT PRIMARY KEY,
27
+ from_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
28
+ to_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
29
+ relation TEXT NOT NULL,
30
+ properties TEXT DEFAULT '{}',
31
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
32
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
33
+ source TEXT,
34
+ confidence REAL DEFAULT 1.0
35
+ );
36
+
37
+ -- Memory log (audit trail of extractions)
38
+ CREATE TABLE IF NOT EXISTS memory_log (
39
+ id TEXT PRIMARY KEY,
40
+ raw_text TEXT NOT NULL,
41
+ extracted_entities TEXT DEFAULT '[]',
42
+ extracted_relations TEXT DEFAULT '[]',
43
+ timestamp TEXT NOT NULL DEFAULT (datetime('now')),
44
+ session_id TEXT
45
+ );
46
+
47
+ -- Indexes for fast lookups
48
+ CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
49
+ CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name COLLATE NOCASE);
50
+ CREATE INDEX IF NOT EXISTS idx_rel_from ON relationships(from_id);
51
+ CREATE INDEX IF NOT EXISTS idx_rel_to ON relationships(to_id);
52
+ CREATE INDEX IF NOT EXISTS idx_rel_relation ON relationships(relation);
53
+ CREATE INDEX IF NOT EXISTS idx_rel_pair ON relationships(from_id, to_id, relation);
54
+
55
+ -- Full-text search on entities
56
+ CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
57
+ name,
58
+ type,
59
+ properties,
60
+ content=entities,
61
+ content_rowid=rowid
62
+ );
63
+
64
+ -- FTS triggers to keep in sync
65
+ CREATE TRIGGER IF NOT EXISTS entities_ai AFTER INSERT ON entities BEGIN
66
+ INSERT INTO entities_fts(rowid, name, type, properties)
67
+ VALUES (new.rowid, new.name, new.type, new.properties);
68
+ END;
69
+
70
+ CREATE TRIGGER IF NOT EXISTS entities_ad AFTER DELETE ON entities BEGIN
71
+ INSERT INTO entities_fts(entities_fts, rowid, name, type, properties)
72
+ VALUES ('delete', old.rowid, old.name, old.type, old.properties);
73
+ END;
74
+
75
+ CREATE TRIGGER IF NOT EXISTS entities_au AFTER UPDATE ON entities BEGIN
76
+ INSERT INTO entities_fts(entities_fts, rowid, name, type, properties)
77
+ VALUES ('delete', old.rowid, old.name, old.type, old.properties);
78
+ INSERT INTO entities_fts(rowid, name, type, properties)
79
+ VALUES (new.rowid, new.name, new.type, new.properties);
80
+ END;
81
+ `;
82
+ export class SchemaManager {
83
+ db;
84
+ constructor(dbPath) {
85
+ // Ensure directory exists
86
+ const dir = resolve(dbPath, '..');
87
+ mkdirSync(dir, { recursive: true });
88
+ this.db = new Database(dbPath);
89
+ this.db.pragma('journal_mode = WAL');
90
+ this.db.pragma('foreign_keys = ON');
91
+ }
92
+ /** Initialize schema (idempotent) */
93
+ initialize() {
94
+ this.db.exec(SCHEMA_SQL);
95
+ // Set schema version
96
+ const stmt = this.db.prepare(`INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_version', ?)`);
97
+ stmt.run(String(SCHEMA_VERSION));
98
+ return this.db;
99
+ }
100
+ /** Get current schema version */
101
+ getVersion() {
102
+ try {
103
+ const row = this.db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
104
+ return row ? parseInt(row.value, 10) : 0;
105
+ }
106
+ catch {
107
+ return 0;
108
+ }
109
+ }
110
+ /** Close database connection */
111
+ close() {
112
+ this.db.close();
113
+ }
114
+ }
115
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/graph/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4ElB,CAAC;AAEF,MAAM,OAAO,aAAa;IAChB,EAAE,CAAoB;IAE9B,YAAY,MAAc;QACxB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpC,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACtC,CAAC;IAED,qCAAqC;IACrC,UAAU;QACR,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEzB,qBAAqB;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,wEAAwE,CACzE,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;QAEjC,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAED,iCAAiC;IACjC,UAAU;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,sDAAsD,CACvD,CAAC,GAAG,EAAmC,CAAC;YACzC,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}