@memextend/core 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.
- package/dist/embedding/index.d.ts +3 -0
- package/dist/embedding/index.d.ts.map +1 -0
- package/dist/embedding/index.js +4 -0
- package/dist/embedding/index.js.map +1 -0
- package/dist/embedding/local.d.ts +54 -0
- package/dist/embedding/local.d.ts.map +1 -0
- package/dist/embedding/local.js +162 -0
- package/dist/embedding/local.js.map +1 -0
- package/dist/embedding/local.test.d.ts +2 -0
- package/dist/embedding/local.test.d.ts.map +1 -0
- package/dist/embedding/local.test.js +73 -0
- package/dist/embedding/local.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/capture.d.ts +102 -0
- package/dist/memory/capture.d.ts.map +1 -0
- package/dist/memory/capture.js +249 -0
- package/dist/memory/capture.js.map +1 -0
- package/dist/memory/capture.test.d.ts +2 -0
- package/dist/memory/capture.test.d.ts.map +1 -0
- package/dist/memory/capture.test.js +168 -0
- package/dist/memory/capture.test.js.map +1 -0
- package/dist/memory/deduplicate.d.ts +31 -0
- package/dist/memory/deduplicate.d.ts.map +1 -0
- package/dist/memory/deduplicate.js +64 -0
- package/dist/memory/deduplicate.js.map +1 -0
- package/dist/memory/deduplicate.test.d.ts +2 -0
- package/dist/memory/deduplicate.test.d.ts.map +1 -0
- package/dist/memory/deduplicate.test.js +116 -0
- package/dist/memory/deduplicate.test.js.map +1 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/retrieve.d.ts +62 -0
- package/dist/memory/retrieve.d.ts.map +1 -0
- package/dist/memory/retrieve.js +218 -0
- package/dist/memory/retrieve.js.map +1 -0
- package/dist/memory/retrieve.test.d.ts +2 -0
- package/dist/memory/retrieve.test.d.ts.map +1 -0
- package/dist/memory/retrieve.test.js +177 -0
- package/dist/memory/retrieve.test.js.map +1 -0
- package/dist/memory/types.d.ts +36 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +4 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/types.test.d.ts +2 -0
- package/dist/memory/types.test.d.ts.map +1 -0
- package/dist/memory/types.test.js +31 -0
- package/dist/memory/types.test.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/lancedb.d.ts +24 -0
- package/dist/storage/lancedb.d.ts.map +1 -0
- package/dist/storage/lancedb.js +106 -0
- package/dist/storage/lancedb.js.map +1 -0
- package/dist/storage/lancedb.test.d.ts +2 -0
- package/dist/storage/lancedb.test.d.ts.map +1 -0
- package/dist/storage/lancedb.test.js +67 -0
- package/dist/storage/lancedb.test.js.map +1 -0
- package/dist/storage/sqlite.d.ts +68 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +354 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/storage/sqlite.test.d.ts +2 -0
- package/dist/storage/sqlite.test.d.ts.map +1 -0
- package/dist/storage/sqlite.test.js +137 -0
- package/dist/storage/sqlite.test.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/project.d.ts +13 -0
- package/dist/utils/project.d.ts.map +1 -0
- package/dist/utils/project.js +37 -0
- package/dist/utils/project.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// packages/core/src/storage/sqlite.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
export class SQLiteStorage {
|
|
5
|
+
db;
|
|
6
|
+
constructor(dbPath) {
|
|
7
|
+
this.db = new Database(dbPath);
|
|
8
|
+
this.db.pragma('journal_mode = WAL');
|
|
9
|
+
this.initialize();
|
|
10
|
+
}
|
|
11
|
+
initialize() {
|
|
12
|
+
this.db.exec(`
|
|
13
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
14
|
+
id TEXT PRIMARY KEY,
|
|
15
|
+
project_id TEXT,
|
|
16
|
+
content TEXT NOT NULL,
|
|
17
|
+
type TEXT NOT NULL,
|
|
18
|
+
source_tool TEXT,
|
|
19
|
+
created_at TEXT NOT NULL,
|
|
20
|
+
session_id TEXT,
|
|
21
|
+
metadata TEXT
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
name TEXT NOT NULL,
|
|
27
|
+
path TEXT NOT NULL,
|
|
28
|
+
created_at TEXT NOT NULL
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS global_profile (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
key TEXT NOT NULL,
|
|
34
|
+
content TEXT NOT NULL,
|
|
35
|
+
created_at TEXT NOT NULL
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
39
|
+
content,
|
|
40
|
+
content='memories',
|
|
41
|
+
content_rowid='rowid'
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
45
|
+
INSERT INTO memories_fts(rowid, content) VALUES (NEW.rowid, NEW.content);
|
|
46
|
+
END;
|
|
47
|
+
|
|
48
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
49
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES('delete', OLD.rowid, OLD.content);
|
|
50
|
+
END;
|
|
51
|
+
|
|
52
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
53
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES('delete', OLD.rowid, OLD.content);
|
|
54
|
+
INSERT INTO memories_fts(rowid, content) VALUES (NEW.rowid, NEW.content);
|
|
55
|
+
END;
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
getTables() {
|
|
59
|
+
const rows = this.db.prepare(`
|
|
60
|
+
SELECT name FROM sqlite_master
|
|
61
|
+
WHERE type='table' OR type='virtual table'
|
|
62
|
+
`).all();
|
|
63
|
+
return rows.map(r => r.name);
|
|
64
|
+
}
|
|
65
|
+
insertMemory(memory) {
|
|
66
|
+
const stmt = this.db.prepare(`
|
|
67
|
+
INSERT INTO memories (id, project_id, content, type, source_tool, created_at, session_id, metadata)
|
|
68
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
69
|
+
`);
|
|
70
|
+
stmt.run(memory.id, memory.projectId, memory.content, memory.type, memory.sourceTool, memory.createdAt, memory.sessionId, memory.metadata ? JSON.stringify(memory.metadata) : null);
|
|
71
|
+
}
|
|
72
|
+
getMemory(id) {
|
|
73
|
+
const row = this.db.prepare('SELECT * FROM memories WHERE id = ?').get(id);
|
|
74
|
+
if (!row)
|
|
75
|
+
return null;
|
|
76
|
+
return this.rowToMemory(row);
|
|
77
|
+
}
|
|
78
|
+
getAllMemories(projectId, limit = 100) {
|
|
79
|
+
let query = 'SELECT * FROM memories';
|
|
80
|
+
const params = [];
|
|
81
|
+
if (projectId) {
|
|
82
|
+
query += ' WHERE project_id = ?';
|
|
83
|
+
params.push(projectId);
|
|
84
|
+
}
|
|
85
|
+
query += ' ORDER BY created_at DESC LIMIT ?';
|
|
86
|
+
params.push(limit);
|
|
87
|
+
const rows = this.db.prepare(query).all(...params);
|
|
88
|
+
return rows.map(row => this.rowToMemory(row));
|
|
89
|
+
}
|
|
90
|
+
searchFTS(query, limit = 10) {
|
|
91
|
+
const rows = this.db.prepare(`
|
|
92
|
+
SELECT m.*, bm25(memories_fts) as score
|
|
93
|
+
FROM memories_fts fts
|
|
94
|
+
JOIN memories m ON m.rowid = fts.rowid
|
|
95
|
+
WHERE memories_fts MATCH ?
|
|
96
|
+
ORDER BY score
|
|
97
|
+
LIMIT ?
|
|
98
|
+
`).all(query, limit);
|
|
99
|
+
return rows.map(row => ({
|
|
100
|
+
memory: this.rowToMemory(row),
|
|
101
|
+
score: Math.abs(row.score),
|
|
102
|
+
source: 'fts'
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
getRecentMemories(projectId, limit = 0, days = 0) {
|
|
106
|
+
// Build query conditionally based on whether days is 0 (unlimited)
|
|
107
|
+
let query = 'SELECT * FROM memories';
|
|
108
|
+
const params = [];
|
|
109
|
+
const conditions = [];
|
|
110
|
+
// Days filter (0 = unlimited/no time constraint)
|
|
111
|
+
if (days > 0) {
|
|
112
|
+
const cutoff = new Date();
|
|
113
|
+
cutoff.setDate(cutoff.getDate() - days);
|
|
114
|
+
conditions.push('created_at > ?');
|
|
115
|
+
params.push(cutoff.toISOString());
|
|
116
|
+
}
|
|
117
|
+
// Project filter
|
|
118
|
+
if (projectId !== null) {
|
|
119
|
+
conditions.push('project_id = ?');
|
|
120
|
+
params.push(projectId);
|
|
121
|
+
}
|
|
122
|
+
if (conditions.length > 0) {
|
|
123
|
+
query += ' WHERE ' + conditions.join(' AND ');
|
|
124
|
+
}
|
|
125
|
+
query += ' ORDER BY created_at DESC';
|
|
126
|
+
// Limit (0 = unlimited)
|
|
127
|
+
if (limit > 0) {
|
|
128
|
+
query += ' LIMIT ?';
|
|
129
|
+
params.push(limit);
|
|
130
|
+
}
|
|
131
|
+
const rows = this.db.prepare(query).all(...params);
|
|
132
|
+
return rows.map(row => this.rowToMemory(row));
|
|
133
|
+
}
|
|
134
|
+
deleteMemory(id) {
|
|
135
|
+
const result = this.db.prepare('DELETE FROM memories WHERE id = ?').run(id);
|
|
136
|
+
return result.changes > 0;
|
|
137
|
+
}
|
|
138
|
+
updateMemory(id, content) {
|
|
139
|
+
// The FTS index is automatically updated by the memories_au trigger
|
|
140
|
+
const result = this.db.prepare('UPDATE memories SET content = ? WHERE id = ?').run(content, id);
|
|
141
|
+
return result.changes > 0;
|
|
142
|
+
}
|
|
143
|
+
deleteAllMemories(projectId) {
|
|
144
|
+
if (projectId) {
|
|
145
|
+
const result = this.db.prepare('DELETE FROM memories WHERE project_id = ?').run(projectId);
|
|
146
|
+
return result.changes;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const result = this.db.prepare('DELETE FROM memories').run();
|
|
150
|
+
return result.changes;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
deleteMemoriesBefore(date, projectId) {
|
|
154
|
+
const timestamp = date.toISOString();
|
|
155
|
+
if (projectId) {
|
|
156
|
+
const result = this.db.prepare('DELETE FROM memories WHERE created_at < ? AND project_id = ?').run(timestamp, projectId);
|
|
157
|
+
return result.changes;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const result = this.db.prepare('DELETE FROM memories WHERE created_at < ?').run(timestamp);
|
|
161
|
+
return result.changes;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Project methods
|
|
165
|
+
insertProject(project) {
|
|
166
|
+
const stmt = this.db.prepare(`
|
|
167
|
+
INSERT OR REPLACE INTO projects (id, name, path, created_at)
|
|
168
|
+
VALUES (?, ?, ?, ?)
|
|
169
|
+
`);
|
|
170
|
+
stmt.run(project.id, project.name, project.path, project.createdAt);
|
|
171
|
+
}
|
|
172
|
+
getProject(id) {
|
|
173
|
+
const row = this.db.prepare('SELECT * FROM projects WHERE id = ?').get(id);
|
|
174
|
+
if (!row)
|
|
175
|
+
return null;
|
|
176
|
+
return {
|
|
177
|
+
id: row.id,
|
|
178
|
+
name: row.name,
|
|
179
|
+
path: row.path,
|
|
180
|
+
createdAt: row.created_at
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Find a project by name (case-insensitive).
|
|
185
|
+
* Returns the first matching project, preferring projects with a path set.
|
|
186
|
+
*/
|
|
187
|
+
getProjectByName(name) {
|
|
188
|
+
// First try to find a project with a path (created by hooks)
|
|
189
|
+
const rowWithPath = this.db.prepare('SELECT * FROM projects WHERE LOWER(name) = LOWER(?) AND path != \'\' ORDER BY created_at ASC LIMIT 1').get(name);
|
|
190
|
+
if (rowWithPath) {
|
|
191
|
+
return {
|
|
192
|
+
id: rowWithPath.id,
|
|
193
|
+
name: rowWithPath.name,
|
|
194
|
+
path: rowWithPath.path,
|
|
195
|
+
createdAt: rowWithPath.created_at
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// Fall back to any project with that name
|
|
199
|
+
const row = this.db.prepare('SELECT * FROM projects WHERE LOWER(name) = LOWER(?) ORDER BY created_at ASC LIMIT 1').get(name);
|
|
200
|
+
if (!row)
|
|
201
|
+
return null;
|
|
202
|
+
return {
|
|
203
|
+
id: row.id,
|
|
204
|
+
name: row.name,
|
|
205
|
+
path: row.path,
|
|
206
|
+
createdAt: row.created_at
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Delete a project and all its memories.
|
|
211
|
+
* @returns Object with counts of deleted project and memories
|
|
212
|
+
*/
|
|
213
|
+
deleteProject(projectId) {
|
|
214
|
+
// Delete all memories for this project first
|
|
215
|
+
const memoriesResult = this.db.prepare('DELETE FROM memories WHERE project_id = ?').run(projectId);
|
|
216
|
+
// Delete the project
|
|
217
|
+
const projectResult = this.db.prepare('DELETE FROM projects WHERE id = ?').run(projectId);
|
|
218
|
+
return {
|
|
219
|
+
projectDeleted: projectResult.changes > 0,
|
|
220
|
+
memoriesDeleted: memoriesResult.changes
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Get all projects.
|
|
225
|
+
*/
|
|
226
|
+
getAllProjects() {
|
|
227
|
+
const rows = this.db.prepare('SELECT * FROM projects ORDER BY name ASC').all();
|
|
228
|
+
return rows.map(row => ({
|
|
229
|
+
id: row.id,
|
|
230
|
+
name: row.name,
|
|
231
|
+
path: row.path,
|
|
232
|
+
createdAt: row.created_at
|
|
233
|
+
}));
|
|
234
|
+
}
|
|
235
|
+
// Global profile methods
|
|
236
|
+
insertGlobalProfile(profile) {
|
|
237
|
+
const stmt = this.db.prepare(`
|
|
238
|
+
INSERT INTO global_profile (id, key, content, created_at)
|
|
239
|
+
VALUES (?, ?, ?, ?)
|
|
240
|
+
`);
|
|
241
|
+
stmt.run(profile.id, profile.key, profile.content, profile.createdAt);
|
|
242
|
+
}
|
|
243
|
+
getGlobalProfiles(limit = 10) {
|
|
244
|
+
const rows = this.db.prepare(`
|
|
245
|
+
SELECT * FROM global_profile ORDER BY created_at DESC LIMIT ?
|
|
246
|
+
`).all(limit);
|
|
247
|
+
return rows.map(row => ({
|
|
248
|
+
id: row.id,
|
|
249
|
+
key: row.key,
|
|
250
|
+
content: row.content,
|
|
251
|
+
createdAt: row.created_at
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Delete a specific global profile by ID.
|
|
256
|
+
*/
|
|
257
|
+
deleteGlobalProfile(id) {
|
|
258
|
+
const result = this.db.prepare('DELETE FROM global_profile WHERE id = ?').run(id);
|
|
259
|
+
return result.changes > 0;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Delete all global profiles.
|
|
263
|
+
* @returns Number of profiles deleted
|
|
264
|
+
*/
|
|
265
|
+
deleteAllGlobalProfiles() {
|
|
266
|
+
const result = this.db.prepare('DELETE FROM global_profile').run();
|
|
267
|
+
return result.changes;
|
|
268
|
+
}
|
|
269
|
+
getMemoryCount() {
|
|
270
|
+
const row = this.db.prepare('SELECT COUNT(*) as count FROM memories').get();
|
|
271
|
+
return row.count;
|
|
272
|
+
}
|
|
273
|
+
getMemoryCountByProject(projectId) {
|
|
274
|
+
const row = this.db.prepare('SELECT COUNT(*) as count FROM memories WHERE project_id = ?').get(projectId);
|
|
275
|
+
return row.count;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get IDs of oldest memories for a project, exceeding the limit
|
|
279
|
+
* @returns Array of memory IDs to delete (oldest first)
|
|
280
|
+
*/
|
|
281
|
+
getOldestMemoryIds(projectId, limit) {
|
|
282
|
+
let query;
|
|
283
|
+
let params;
|
|
284
|
+
if (projectId) {
|
|
285
|
+
query = `
|
|
286
|
+
SELECT id FROM memories
|
|
287
|
+
WHERE project_id = ?
|
|
288
|
+
ORDER BY created_at ASC
|
|
289
|
+
LIMIT ?
|
|
290
|
+
`;
|
|
291
|
+
params = [projectId, limit];
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
query = `
|
|
295
|
+
SELECT id FROM memories
|
|
296
|
+
ORDER BY created_at ASC
|
|
297
|
+
LIMIT ?
|
|
298
|
+
`;
|
|
299
|
+
params = [limit];
|
|
300
|
+
}
|
|
301
|
+
const rows = this.db.prepare(query).all(...params);
|
|
302
|
+
return rows.map(row => row.id);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Prune memories to stay within limits
|
|
306
|
+
* @returns Number of memories deleted
|
|
307
|
+
*/
|
|
308
|
+
pruneMemories(options) {
|
|
309
|
+
const deletedIds = [];
|
|
310
|
+
// Prune per-project if limit specified
|
|
311
|
+
if (options.maxPerProject && options.maxPerProject > 0 && options.projectId) {
|
|
312
|
+
const count = this.getMemoryCountByProject(options.projectId);
|
|
313
|
+
if (count > options.maxPerProject) {
|
|
314
|
+
const excess = count - options.maxPerProject;
|
|
315
|
+
const idsToDelete = this.getOldestMemoryIds(options.projectId, excess);
|
|
316
|
+
for (const id of idsToDelete) {
|
|
317
|
+
this.deleteMemory(id);
|
|
318
|
+
deletedIds.push(id);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Prune total if limit specified
|
|
323
|
+
if (options.maxTotal && options.maxTotal > 0) {
|
|
324
|
+
const count = this.getMemoryCount();
|
|
325
|
+
if (count > options.maxTotal) {
|
|
326
|
+
const excess = count - options.maxTotal;
|
|
327
|
+
const idsToDelete = this.getOldestMemoryIds(null, excess);
|
|
328
|
+
for (const id of idsToDelete) {
|
|
329
|
+
if (!deletedIds.includes(id)) {
|
|
330
|
+
this.deleteMemory(id);
|
|
331
|
+
deletedIds.push(id);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return { deleted: deletedIds.length, deletedIds };
|
|
337
|
+
}
|
|
338
|
+
rowToMemory(row) {
|
|
339
|
+
return {
|
|
340
|
+
id: row.id,
|
|
341
|
+
projectId: row.project_id,
|
|
342
|
+
content: row.content,
|
|
343
|
+
type: row.type,
|
|
344
|
+
sourceTool: row.source_tool,
|
|
345
|
+
createdAt: row.created_at,
|
|
346
|
+
sessionId: row.session_id,
|
|
347
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : null
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
close() {
|
|
351
|
+
this.db.close();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,8CAA8C;AAE9C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,MAAM,OAAO,aAAa;IAChB,EAAE,CAAoB;IAE9B,YAAY,MAAc;QACxB,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4CZ,CAAC,CAAC;IACL,CAAC;IAED,SAAS;QACP,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC,GAAG,EAAwB,CAAC;QAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,YAAY,CAAC,MAAc;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CACN,MAAM,CAAC,EAAE,EACT,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CACzD,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAQ,CAAC;QAClF,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,cAAc,CAAC,SAAkB,EAAE,QAAgB,GAAG;QACpD,IAAI,KAAK,GAAG,wBAAwB,CAAC;QACrC,MAAM,MAAM,GAAU,EAAE,CAAC;QAEzB,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,IAAI,uBAAuB,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QAED,KAAK,IAAI,mCAAmC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAU,CAAC;QAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,SAAS,CAAC,KAAa,EAAE,QAAgB,EAAE;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;KAO5B,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAU,CAAC;QAE9B,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtB,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;YAC7B,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;YAC1B,MAAM,EAAE,KAAc;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,iBAAiB,CAAC,SAAwB,EAAE,QAAgB,CAAC,EAAE,OAAe,CAAC;QAC7E,mEAAmE;QACnE,IAAI,KAAK,GAAG,wBAAwB,CAAC;QACrC,MAAM,MAAM,GAAU,EAAE,CAAC;QACzB,MAAM,UAAU,GAAa,EAAE,CAAC;QAEhC,iDAAiD;QACjD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;YACxC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,iBAAiB;QACjB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,IAAI,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAED,KAAK,IAAI,2BAA2B,CAAC;QAErC,wBAAwB;QACxB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,KAAK,IAAI,UAAU,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAU,CAAC;QAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,YAAY,CAAC,EAAU;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5E,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,YAAY,CAAC,EAAU,EAAE,OAAe;QACtC,oEAAoE;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC5B,8CAA8C,CAC/C,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAEnB,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,iBAAiB,CAAC,SAAkB;QAClC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3F,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,EAAE,CAAC;YAC7D,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,IAAU,EAAE,SAAkB;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC5B,8DAA8D,CAC/D,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC5B,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3F,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,aAAa,CAAC,OAAgB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACtE,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAQ,CAAC;QAClF,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,GAAG,CAAC,UAAU;SAC1B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,IAAY;QAC3B,6DAA6D;QAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACjC,sGAAsG,CACvG,CAAC,GAAG,CAAC,IAAI,CAAQ,CAAC;QAEnB,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO;gBACL,EAAE,EAAE,WAAW,CAAC,EAAE;gBAClB,IAAI,EAAE,WAAW,CAAC,IAAI;gBACtB,IAAI,EAAE,WAAW,CAAC,IAAI;gBACtB,SAAS,EAAE,WAAW,CAAC,UAAU;aAClC,CAAC;QACJ,CAAC;QAED,0CAA0C;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,qFAAqF,CACtF,CAAC,GAAG,CAAC,IAAI,CAAQ,CAAC;QAEnB,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,GAAG,CAAC,UAAU;SAC1B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,SAAiB;QAC7B,6CAA6C;QAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEnG,qBAAqB;QACrB,MAAM,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAE1F,OAAO;YACL,cAAc,EAAE,aAAa,CAAC,OAAO,GAAG,CAAC;YACzC,eAAe,EAAE,cAAc,CAAC,OAAO;SACxC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,EAAW,CAAC;QACxF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,GAAG,CAAC,UAAU;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,yBAAyB;IACzB,mBAAmB,CAAC,OAAsB;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxE,CAAC;IAED,iBAAiB,CAAC,QAAgB,EAAE;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;KAE5B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAU,CAAC;QACvB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,UAAU;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,EAAU;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,uBAAuB;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,GAAG,EAAE,CAAC;QACnE,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,cAAc;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC,GAAG,EAAS,CAAC;QACnF,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,uBAAuB,CAAC,SAAiB;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,6DAA6D,CAC9D,CAAC,GAAG,CAAC,SAAS,CAAQ,CAAC;QACxB,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,kBAAkB,CAAC,SAAwB,EAAE,KAAa;QACxD,IAAI,KAAa,CAAC;QAClB,IAAI,MAAa,CAAC;QAElB,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,GAAG;;;;;OAKP,CAAC;YACF,MAAM,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,KAAK,GAAG;;;;OAIP,CAAC;YACF,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAU,CAAC;QAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,OAIb;QACC,MAAM,UAAU,GAAa,EAAE,CAAC;QAEhC,uCAAuC;QACvC,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,aAAa,GAAG,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,KAAK,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;gBAClC,MAAM,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;gBAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBACvE,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;oBAC7B,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;oBACtB,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACpC,IAAI,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;gBACxC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC1D,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;oBAC7B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;wBAC7B,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;wBACtB,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACtB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;IACpD,CAAC;IAEO,WAAW,CAAC,GAAQ;QAC1B,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;SACzD,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.test.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// packages/core/src/storage/sqlite.test.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
4
|
+
import { mkdtemp, rm } from 'fs/promises';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { tmpdir } from 'os';
|
|
7
|
+
import { SQLiteStorage } from './sqlite.js';
|
|
8
|
+
describe('SQLiteStorage', () => {
|
|
9
|
+
let tempDir;
|
|
10
|
+
let storage;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
tempDir = await mkdtemp(join(tmpdir(), 'memextend-test-'));
|
|
13
|
+
storage = new SQLiteStorage(join(tempDir, 'test.db'));
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
storage.close();
|
|
17
|
+
await rm(tempDir, { recursive: true });
|
|
18
|
+
});
|
|
19
|
+
it('should initialize database with tables', () => {
|
|
20
|
+
const tables = storage.getTables();
|
|
21
|
+
expect(tables).toContain('memories');
|
|
22
|
+
expect(tables).toContain('memories_fts');
|
|
23
|
+
expect(tables).toContain('projects');
|
|
24
|
+
expect(tables).toContain('global_profile');
|
|
25
|
+
});
|
|
26
|
+
it('should insert and retrieve a memory', () => {
|
|
27
|
+
const memory = {
|
|
28
|
+
id: 'test-1',
|
|
29
|
+
projectId: 'proj-1',
|
|
30
|
+
content: 'Test memory content',
|
|
31
|
+
type: 'tool_capture',
|
|
32
|
+
sourceTool: 'Edit',
|
|
33
|
+
createdAt: new Date().toISOString(),
|
|
34
|
+
sessionId: 'sess-1',
|
|
35
|
+
metadata: { file: 'test.ts' }
|
|
36
|
+
};
|
|
37
|
+
storage.insertMemory(memory);
|
|
38
|
+
const retrieved = storage.getMemory('test-1');
|
|
39
|
+
expect(retrieved).not.toBeNull();
|
|
40
|
+
expect(retrieved?.content).toBe('Test memory content');
|
|
41
|
+
expect(retrieved?.sourceTool).toBe('Edit');
|
|
42
|
+
expect(retrieved?.metadata).toEqual({ file: 'test.ts' });
|
|
43
|
+
});
|
|
44
|
+
it('should search memories with FTS', () => {
|
|
45
|
+
storage.insertMemory({
|
|
46
|
+
id: 'test-1',
|
|
47
|
+
projectId: 'proj-1',
|
|
48
|
+
content: 'Redis caching implementation',
|
|
49
|
+
type: 'tool_capture',
|
|
50
|
+
sourceTool: 'Edit',
|
|
51
|
+
createdAt: new Date().toISOString(),
|
|
52
|
+
sessionId: null,
|
|
53
|
+
metadata: null
|
|
54
|
+
});
|
|
55
|
+
storage.insertMemory({
|
|
56
|
+
id: 'test-2',
|
|
57
|
+
projectId: 'proj-1',
|
|
58
|
+
content: 'Authentication with JWT',
|
|
59
|
+
type: 'tool_capture',
|
|
60
|
+
sourceTool: 'Edit',
|
|
61
|
+
createdAt: new Date().toISOString(),
|
|
62
|
+
sessionId: null,
|
|
63
|
+
metadata: null
|
|
64
|
+
});
|
|
65
|
+
const results = storage.searchFTS('Redis');
|
|
66
|
+
expect(results.length).toBe(1);
|
|
67
|
+
expect(results[0].memory.id).toBe('test-1');
|
|
68
|
+
expect(results[0].source).toBe('fts');
|
|
69
|
+
});
|
|
70
|
+
it('should get recent memories', () => {
|
|
71
|
+
const now = new Date();
|
|
72
|
+
const oldDate = new Date();
|
|
73
|
+
oldDate.setDate(oldDate.getDate() - 10);
|
|
74
|
+
storage.insertMemory({
|
|
75
|
+
id: 'recent',
|
|
76
|
+
projectId: 'proj-1',
|
|
77
|
+
content: 'Recent memory',
|
|
78
|
+
type: 'tool_capture',
|
|
79
|
+
sourceTool: 'Edit',
|
|
80
|
+
createdAt: now.toISOString(),
|
|
81
|
+
sessionId: null,
|
|
82
|
+
metadata: null
|
|
83
|
+
});
|
|
84
|
+
storage.insertMemory({
|
|
85
|
+
id: 'old',
|
|
86
|
+
projectId: 'proj-1',
|
|
87
|
+
content: 'Old memory',
|
|
88
|
+
type: 'tool_capture',
|
|
89
|
+
sourceTool: 'Edit',
|
|
90
|
+
createdAt: oldDate.toISOString(),
|
|
91
|
+
sessionId: null,
|
|
92
|
+
metadata: null
|
|
93
|
+
});
|
|
94
|
+
const results = storage.getRecentMemories('proj-1', 10, 7);
|
|
95
|
+
expect(results.length).toBe(1);
|
|
96
|
+
expect(results[0].id).toBe('recent');
|
|
97
|
+
});
|
|
98
|
+
it('should delete a memory', () => {
|
|
99
|
+
storage.insertMemory({
|
|
100
|
+
id: 'to-delete',
|
|
101
|
+
projectId: 'proj-1',
|
|
102
|
+
content: 'Will be deleted',
|
|
103
|
+
type: 'manual',
|
|
104
|
+
sourceTool: null,
|
|
105
|
+
createdAt: new Date().toISOString(),
|
|
106
|
+
sessionId: null,
|
|
107
|
+
metadata: null
|
|
108
|
+
});
|
|
109
|
+
expect(storage.getMemory('to-delete')).not.toBeNull();
|
|
110
|
+
const deleted = storage.deleteMemory('to-delete');
|
|
111
|
+
expect(deleted).toBe(true);
|
|
112
|
+
expect(storage.getMemory('to-delete')).toBeNull();
|
|
113
|
+
});
|
|
114
|
+
it('should handle projects', () => {
|
|
115
|
+
storage.insertProject({
|
|
116
|
+
id: 'proj-1',
|
|
117
|
+
name: 'my-project',
|
|
118
|
+
path: '/home/user/my-project',
|
|
119
|
+
createdAt: new Date().toISOString()
|
|
120
|
+
});
|
|
121
|
+
const project = storage.getProject('proj-1');
|
|
122
|
+
expect(project).not.toBeNull();
|
|
123
|
+
expect(project?.name).toBe('my-project');
|
|
124
|
+
});
|
|
125
|
+
it('should handle global profiles', () => {
|
|
126
|
+
storage.insertGlobalProfile({
|
|
127
|
+
id: 'pref-1',
|
|
128
|
+
key: 'preference',
|
|
129
|
+
content: 'Prefers Vitest over Jest',
|
|
130
|
+
createdAt: new Date().toISOString()
|
|
131
|
+
});
|
|
132
|
+
const profiles = storage.getGlobalProfiles(10);
|
|
133
|
+
expect(profiles.length).toBe(1);
|
|
134
|
+
expect(profiles[0].key).toBe('preference');
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
//# sourceMappingURL=sqlite.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.test.js","sourceRoot":"","sources":["../../src/storage/sqlite.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,8CAA8C;AAE9C,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get a project ID from a directory path.
|
|
3
|
+
* Uses git root if available, otherwise hashes the path.
|
|
4
|
+
* @param cwd - The directory path to get project ID for
|
|
5
|
+
* @returns A 16-character hex string identifying the project
|
|
6
|
+
*/
|
|
7
|
+
export declare function getProjectId(cwd: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Get a project ID for the current working directory.
|
|
10
|
+
* @returns A 16-character hex string identifying the project, or null if unable to determine
|
|
11
|
+
*/
|
|
12
|
+
export declare function getCurrentProjectId(): string | null;
|
|
13
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYhD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAMnD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// packages/core/src/utils/project.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { createHash } from 'crypto';
|
|
5
|
+
/**
|
|
6
|
+
* Get a project ID from a directory path.
|
|
7
|
+
* Uses git root if available, otherwise hashes the path.
|
|
8
|
+
* @param cwd - The directory path to get project ID for
|
|
9
|
+
* @returns A 16-character hex string identifying the project
|
|
10
|
+
*/
|
|
11
|
+
export function getProjectId(cwd) {
|
|
12
|
+
try {
|
|
13
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
|
14
|
+
cwd,
|
|
15
|
+
encoding: 'utf-8',
|
|
16
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
17
|
+
}).trim();
|
|
18
|
+
return createHash('sha256').update(gitRoot).digest('hex').slice(0, 16);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Not a git repository, use path hash
|
|
22
|
+
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a project ID for the current working directory.
|
|
27
|
+
* @returns A 16-character hex string identifying the project, or null if unable to determine
|
|
28
|
+
*/
|
|
29
|
+
export function getCurrentProjectId() {
|
|
30
|
+
try {
|
|
31
|
+
return getProjectId(process.cwd());
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,8CAA8C;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACxD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;QACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@memextend/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Core memory storage and retrieval for memextend - local AI memory extension",
|
|
5
|
+
"author": "ZodTTD LLC <repo@zodttd.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@lancedb/lancedb": "^0.4.0",
|
|
23
|
+
"better-sqlite3": "^12.6.2",
|
|
24
|
+
"node-llama-cpp": "^3.0.0",
|
|
25
|
+
"uuid": "^9.0.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/better-sqlite3": "^7.6.8",
|
|
29
|
+
"@types/uuid": "^9.0.7"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/zodttd/memextend.git",
|
|
34
|
+
"directory": "packages/core"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/zodttd/memextend/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/zodttd/memextend#readme",
|
|
40
|
+
"keywords": [
|
|
41
|
+
"memextend",
|
|
42
|
+
"ai-memory",
|
|
43
|
+
"llm",
|
|
44
|
+
"claude",
|
|
45
|
+
"vector-search",
|
|
46
|
+
"sqlite",
|
|
47
|
+
"lancedb",
|
|
48
|
+
"embeddings",
|
|
49
|
+
"semantic-search"
|
|
50
|
+
],
|
|
51
|
+
"files": [
|
|
52
|
+
"dist",
|
|
53
|
+
"README.md"
|
|
54
|
+
],
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18.0.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|