ai-mind-map 1.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/LICENSE +21 -0
- package/README.md +554 -0
- package/dist/change-tracker/change-log.d.ts +160 -0
- package/dist/change-tracker/change-log.d.ts.map +1 -0
- package/dist/change-tracker/change-log.js +507 -0
- package/dist/change-tracker/change-log.js.map +1 -0
- package/dist/change-tracker/diff-engine.d.ts +149 -0
- package/dist/change-tracker/diff-engine.d.ts.map +1 -0
- package/dist/change-tracker/diff-engine.js +530 -0
- package/dist/change-tracker/diff-engine.js.map +1 -0
- package/dist/change-tracker/watcher.d.ts +137 -0
- package/dist/change-tracker/watcher.d.ts.map +1 -0
- package/dist/change-tracker/watcher.js +300 -0
- package/dist/change-tracker/watcher.js.map +1 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +937 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +222 -0
- package/dist/config.js.map +1 -0
- package/dist/context/compressor.d.ts +49 -0
- package/dist/context/compressor.d.ts.map +1 -0
- package/dist/context/compressor.js +769 -0
- package/dist/context/compressor.js.map +1 -0
- package/dist/context/progressive-disclosure.d.ts +71 -0
- package/dist/context/progressive-disclosure.d.ts.map +1 -0
- package/dist/context/progressive-disclosure.js +470 -0
- package/dist/context/progressive-disclosure.js.map +1 -0
- package/dist/context/token-budget.d.ts +121 -0
- package/dist/context/token-budget.d.ts.map +1 -0
- package/dist/context/token-budget.js +282 -0
- package/dist/context/token-budget.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +944 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +66 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +946 -0
- package/dist/install.js.map +1 -0
- package/dist/knowledge-graph/architecture.d.ts +213 -0
- package/dist/knowledge-graph/architecture.d.ts.map +1 -0
- package/dist/knowledge-graph/architecture.js +585 -0
- package/dist/knowledge-graph/architecture.js.map +1 -0
- package/dist/knowledge-graph/cypher.d.ts +113 -0
- package/dist/knowledge-graph/cypher.d.ts.map +1 -0
- package/dist/knowledge-graph/cypher.js +1051 -0
- package/dist/knowledge-graph/cypher.js.map +1 -0
- package/dist/knowledge-graph/dead-code.d.ts +121 -0
- package/dist/knowledge-graph/dead-code.d.ts.map +1 -0
- package/dist/knowledge-graph/dead-code.js +331 -0
- package/dist/knowledge-graph/dead-code.js.map +1 -0
- package/dist/knowledge-graph/flow-analyzer.d.ts +167 -0
- package/dist/knowledge-graph/flow-analyzer.d.ts.map +1 -0
- package/dist/knowledge-graph/flow-analyzer.js +739 -0
- package/dist/knowledge-graph/flow-analyzer.js.map +1 -0
- package/dist/knowledge-graph/graph.d.ts +291 -0
- package/dist/knowledge-graph/graph.d.ts.map +1 -0
- package/dist/knowledge-graph/graph.js +978 -0
- package/dist/knowledge-graph/graph.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +17 -0
- package/dist/knowledge-graph/index.d.ts.map +1 -0
- package/dist/knowledge-graph/index.js +14 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/knowledge-graph/indexer.d.ts +112 -0
- package/dist/knowledge-graph/indexer.d.ts.map +1 -0
- package/dist/knowledge-graph/indexer.js +506 -0
- package/dist/knowledge-graph/indexer.js.map +1 -0
- package/dist/knowledge-graph/pagerank.d.ts +141 -0
- package/dist/knowledge-graph/pagerank.d.ts.map +1 -0
- package/dist/knowledge-graph/pagerank.js +493 -0
- package/dist/knowledge-graph/pagerank.js.map +1 -0
- package/dist/knowledge-graph/parser.d.ts +55 -0
- package/dist/knowledge-graph/parser.d.ts.map +1 -0
- package/dist/knowledge-graph/parser.js +1090 -0
- package/dist/knowledge-graph/parser.js.map +1 -0
- package/dist/knowledge-graph/snapshot.d.ts +107 -0
- package/dist/knowledge-graph/snapshot.d.ts.map +1 -0
- package/dist/knowledge-graph/snapshot.js +435 -0
- package/dist/knowledge-graph/snapshot.js.map +1 -0
- package/dist/memory/decision-log.d.ts +151 -0
- package/dist/memory/decision-log.d.ts.map +1 -0
- package/dist/memory/decision-log.js +482 -0
- package/dist/memory/decision-log.js.map +1 -0
- package/dist/memory/persistent-memory.d.ts +182 -0
- package/dist/memory/persistent-memory.d.ts.map +1 -0
- package/dist/memory/persistent-memory.js +579 -0
- package/dist/memory/persistent-memory.js.map +1 -0
- package/dist/memory/session-memory.d.ts +165 -0
- package/dist/memory/session-memory.d.ts.map +1 -0
- package/dist/memory/session-memory.js +382 -0
- package/dist/memory/session-memory.js.map +1 -0
- package/dist/stress-test.d.ts +10 -0
- package/dist/stress-test.d.ts.map +1 -0
- package/dist/stress-test.js +258 -0
- package/dist/stress-test.js.map +1 -0
- package/dist/tools/advanced-tools.d.ts +32 -0
- package/dist/tools/advanced-tools.d.ts.map +1 -0
- package/dist/tools/advanced-tools.js +480 -0
- package/dist/tools/advanced-tools.js.map +1 -0
- package/dist/tools/change-tools.d.ts +76 -0
- package/dist/tools/change-tools.d.ts.map +1 -0
- package/dist/tools/change-tools.js +93 -0
- package/dist/tools/change-tools.js.map +1 -0
- package/dist/tools/context-tools.d.ts +68 -0
- package/dist/tools/context-tools.d.ts.map +1 -0
- package/dist/tools/context-tools.js +141 -0
- package/dist/tools/context-tools.js.map +1 -0
- package/dist/tools/debug-tools.d.ts +25 -0
- package/dist/tools/debug-tools.d.ts.map +1 -0
- package/dist/tools/debug-tools.js +286 -0
- package/dist/tools/debug-tools.js.map +1 -0
- package/dist/tools/evolving-tools.d.ts +23 -0
- package/dist/tools/evolving-tools.d.ts.map +1 -0
- package/dist/tools/evolving-tools.js +207 -0
- package/dist/tools/evolving-tools.js.map +1 -0
- package/dist/tools/flow-tools.d.ts +24 -0
- package/dist/tools/flow-tools.d.ts.map +1 -0
- package/dist/tools/flow-tools.js +265 -0
- package/dist/tools/flow-tools.js.map +1 -0
- package/dist/tools/graph-tools.d.ts +71 -0
- package/dist/tools/graph-tools.d.ts.map +1 -0
- package/dist/tools/graph-tools.js +165 -0
- package/dist/tools/graph-tools.js.map +1 -0
- package/dist/tools/memory-tools.d.ts +62 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js +195 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/smart-tools.d.ts +23 -0
- package/dist/tools/smart-tools.d.ts.map +1 -0
- package/dist/tools/smart-tools.js +482 -0
- package/dist/tools/smart-tools.js.map +1 -0
- package/dist/tools/snapshot-tools.d.ts +19 -0
- package/dist/tools/snapshot-tools.d.ts.map +1 -0
- package/dist/tools/snapshot-tools.js +149 -0
- package/dist/tools/snapshot-tools.js.map +1 -0
- package/dist/types.d.ts +181 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/logger.d.ts +59 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +142 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/token-counter.d.ts +51 -0
- package/dist/utils/token-counter.d.ts.map +1 -0
- package/dist/utils/token-counter.js +181 -0
- package/dist/utils/token-counter.js.map +1 -0
- package/install.ps1 +321 -0
- package/install.sh +345 -0
- package/package.json +94 -0
- package/setup.bat +62 -0
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Mind Map — Persistent Memory Store
|
|
3
|
+
*
|
|
4
|
+
* Long-term memory with importance decay, BM25 text search (FTS5),
|
|
5
|
+
* category/tag filtering, deduplication via text similarity, and
|
|
6
|
+
* token-budget-constrained retrieval.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by Mem0's memory lifecycle:
|
|
9
|
+
* create → access (boost) → decay → prune
|
|
10
|
+
*
|
|
11
|
+
* @module memory/persistent-memory
|
|
12
|
+
*/
|
|
13
|
+
// ────────────────────────────────────────────────────────────────
|
|
14
|
+
// Constants
|
|
15
|
+
// ────────────────────────────────────────────────────────────────
|
|
16
|
+
/** Default importance by category (higher = more important). */
|
|
17
|
+
const CATEGORY_IMPORTANCE = {
|
|
18
|
+
architecture: 0.9,
|
|
19
|
+
gotcha: 0.85,
|
|
20
|
+
convention: 0.8,
|
|
21
|
+
decision: 0.8,
|
|
22
|
+
lesson_learned: 0.75,
|
|
23
|
+
dependency: 0.7,
|
|
24
|
+
workflow: 0.7,
|
|
25
|
+
context: 0.6,
|
|
26
|
+
preference: 0.55,
|
|
27
|
+
todo: 0.5,
|
|
28
|
+
};
|
|
29
|
+
/** Rough estimate: 1 token ≈ 4 characters. */
|
|
30
|
+
const CHARS_PER_TOKEN = 4;
|
|
31
|
+
// ────────────────────────────────────────────────────────────────
|
|
32
|
+
// PersistentMemory Class
|
|
33
|
+
// ────────────────────────────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Long-term memory store with decay, boosting, FTS5 search, and deduplication.
|
|
36
|
+
*
|
|
37
|
+
* All mutations are synchronous (better-sqlite3) and WAL-mode safe.
|
|
38
|
+
*/
|
|
39
|
+
export class PersistentMemory {
|
|
40
|
+
db;
|
|
41
|
+
decayRate;
|
|
42
|
+
maxMemories;
|
|
43
|
+
importanceThreshold;
|
|
44
|
+
// ── Prepared statements ────────────────────────────────────
|
|
45
|
+
stmtInsert;
|
|
46
|
+
stmtUpdate;
|
|
47
|
+
stmtDelete;
|
|
48
|
+
stmtGetById;
|
|
49
|
+
stmtBumpAccess;
|
|
50
|
+
stmtAll;
|
|
51
|
+
stmtCount;
|
|
52
|
+
stmtCategoryCount;
|
|
53
|
+
stmtAvgImportance;
|
|
54
|
+
stmtOldest;
|
|
55
|
+
stmtNewest;
|
|
56
|
+
stmtTotalAccess;
|
|
57
|
+
stmtPrunable;
|
|
58
|
+
stmtSearchFts;
|
|
59
|
+
constructor(db, config) {
|
|
60
|
+
this.db = db;
|
|
61
|
+
this.decayRate = config?.decayRate ?? 0.95;
|
|
62
|
+
this.maxMemories = config?.maxMemories ?? 500;
|
|
63
|
+
this.importanceThreshold = config?.importanceThreshold ?? 0.1;
|
|
64
|
+
this.ensureSchema();
|
|
65
|
+
this.prepareStatements();
|
|
66
|
+
}
|
|
67
|
+
// ────────────────────────────────────────────────────────────
|
|
68
|
+
// Schema
|
|
69
|
+
// ────────────────────────────────────────────────────────────
|
|
70
|
+
ensureSchema() {
|
|
71
|
+
this.db.exec(`
|
|
72
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
73
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
74
|
+
category TEXT NOT NULL,
|
|
75
|
+
content TEXT NOT NULL,
|
|
76
|
+
importance REAL NOT NULL,
|
|
77
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
78
|
+
related_files TEXT NOT NULL DEFAULT '[]',
|
|
79
|
+
created_at INTEGER NOT NULL,
|
|
80
|
+
last_accessed_at INTEGER NOT NULL,
|
|
81
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
82
|
+
session_id TEXT NOT NULL DEFAULT '',
|
|
83
|
+
source TEXT NOT NULL DEFAULT 'agent'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_memories_category ON memories(category);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_memories_importance ON memories(importance DESC);
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_memories_accessed ON memories(last_accessed_at DESC);
|
|
89
|
+
`);
|
|
90
|
+
// FTS5 virtual table — created only if it doesn't already exist.
|
|
91
|
+
// We use a content-sync approach: manual sync via triggers.
|
|
92
|
+
try {
|
|
93
|
+
this.db.exec(`
|
|
94
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
95
|
+
content,
|
|
96
|
+
category,
|
|
97
|
+
tags,
|
|
98
|
+
content='memories',
|
|
99
|
+
content_rowid='id',
|
|
100
|
+
tokenize='porter unicode61'
|
|
101
|
+
);
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// FTS table may already exist; ignore duplicate errors.
|
|
106
|
+
}
|
|
107
|
+
// Sync triggers — keep FTS in lockstep with the main table.
|
|
108
|
+
this.db.exec(`
|
|
109
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
110
|
+
INSERT INTO memories_fts(rowid, content, category, tags)
|
|
111
|
+
VALUES (new.id, new.content, new.category, new.tags);
|
|
112
|
+
END;
|
|
113
|
+
|
|
114
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
115
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category, tags)
|
|
116
|
+
VALUES ('delete', old.id, old.content, old.category, old.tags);
|
|
117
|
+
END;
|
|
118
|
+
|
|
119
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE OF content, category, tags ON memories BEGIN
|
|
120
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category, tags)
|
|
121
|
+
VALUES ('delete', old.id, old.content, old.category, old.tags);
|
|
122
|
+
INSERT INTO memories_fts(rowid, content, category, tags)
|
|
123
|
+
VALUES (new.id, new.content, new.category, new.tags);
|
|
124
|
+
END;
|
|
125
|
+
`);
|
|
126
|
+
}
|
|
127
|
+
prepareStatements() {
|
|
128
|
+
this.stmtInsert = this.db.prepare(`
|
|
129
|
+
INSERT INTO memories (category, content, importance, tags, related_files,
|
|
130
|
+
created_at, last_accessed_at, access_count, session_id, source)
|
|
131
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?)
|
|
132
|
+
`);
|
|
133
|
+
this.stmtUpdate = this.db.prepare(`
|
|
134
|
+
UPDATE memories
|
|
135
|
+
SET category = ?, content = ?, importance = ?, tags = ?, related_files = ?,
|
|
136
|
+
last_accessed_at = ?, session_id = ?, source = ?
|
|
137
|
+
WHERE id = ?
|
|
138
|
+
`);
|
|
139
|
+
this.stmtDelete = this.db.prepare(`DELETE FROM memories WHERE id = ?`);
|
|
140
|
+
this.stmtGetById = this.db.prepare(`SELECT * FROM memories WHERE id = ?`);
|
|
141
|
+
this.stmtBumpAccess = this.db.prepare(`
|
|
142
|
+
UPDATE memories
|
|
143
|
+
SET access_count = access_count + 1,
|
|
144
|
+
last_accessed_at = ?,
|
|
145
|
+
importance = MIN(1.0, importance + 0.1)
|
|
146
|
+
WHERE id = ?
|
|
147
|
+
`);
|
|
148
|
+
this.stmtAll = this.db.prepare(`SELECT * FROM memories ORDER BY importance DESC`);
|
|
149
|
+
this.stmtCount = this.db.prepare(`SELECT COUNT(*) AS cnt FROM memories`);
|
|
150
|
+
this.stmtCategoryCount = this.db.prepare(`SELECT category, COUNT(*) AS cnt FROM memories GROUP BY category`);
|
|
151
|
+
this.stmtAvgImportance = this.db.prepare(`SELECT AVG(importance) AS avg FROM memories`);
|
|
152
|
+
this.stmtOldest = this.db.prepare(`SELECT MIN(created_at) AS ts FROM memories`);
|
|
153
|
+
this.stmtNewest = this.db.prepare(`SELECT MAX(created_at) AS ts FROM memories`);
|
|
154
|
+
this.stmtTotalAccess = this.db.prepare(`SELECT SUM(access_count) AS total FROM memories`);
|
|
155
|
+
this.stmtPrunable = this.db.prepare(`
|
|
156
|
+
SELECT id FROM memories
|
|
157
|
+
WHERE importance < ?
|
|
158
|
+
ORDER BY importance ASC, last_accessed_at ASC
|
|
159
|
+
LIMIT ?
|
|
160
|
+
`);
|
|
161
|
+
this.stmtSearchFts = this.db.prepare(`
|
|
162
|
+
SELECT m.*, bm25(memories_fts, 10.0, 5.0, 2.0) AS rank
|
|
163
|
+
FROM memories_fts f
|
|
164
|
+
JOIN memories m ON m.id = f.rowid
|
|
165
|
+
WHERE memories_fts MATCH ?
|
|
166
|
+
ORDER BY rank
|
|
167
|
+
`);
|
|
168
|
+
}
|
|
169
|
+
// ────────────────────────────────────────────────────────────
|
|
170
|
+
// CRUD
|
|
171
|
+
// ────────────────────────────────────────────────────────────
|
|
172
|
+
/**
|
|
173
|
+
* Create a new memory, with automatic deduplication.
|
|
174
|
+
*
|
|
175
|
+
* If a sufficiently similar memory already exists (≥ 0.8 Jaccard similarity
|
|
176
|
+
* on word sets), the existing memory is *merged* instead of creating a
|
|
177
|
+
* duplicate.
|
|
178
|
+
*
|
|
179
|
+
* @returns The memory (new or merged).
|
|
180
|
+
*/
|
|
181
|
+
createMemory(input) {
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const importance = input.importance ?? CATEGORY_IMPORTANCE[input.category] ?? 0.5;
|
|
184
|
+
const tags = input.tags ?? [];
|
|
185
|
+
const relatedFiles = input.relatedFiles ?? [];
|
|
186
|
+
const sessionId = input.sessionId ?? '';
|
|
187
|
+
const source = input.source ?? 'agent';
|
|
188
|
+
// ── Deduplication ────────────────────────────────────────
|
|
189
|
+
const existing = this.findDuplicate(input.content, input.category);
|
|
190
|
+
if (existing) {
|
|
191
|
+
return this.mergeMemory(existing, input, now);
|
|
192
|
+
}
|
|
193
|
+
// ── Insert ───────────────────────────────────────────────
|
|
194
|
+
const info = this.stmtInsert.run(input.category, input.content, importance, JSON.stringify(tags), JSON.stringify(relatedFiles), now, now, sessionId, source);
|
|
195
|
+
// ── Prune if over capacity ───────────────────────────────
|
|
196
|
+
this.pruneIfNeeded();
|
|
197
|
+
return this.rowToMemory({
|
|
198
|
+
id: Number(info.lastInsertRowid),
|
|
199
|
+
category: input.category,
|
|
200
|
+
content: input.content,
|
|
201
|
+
importance,
|
|
202
|
+
tags: JSON.stringify(tags),
|
|
203
|
+
related_files: JSON.stringify(relatedFiles),
|
|
204
|
+
created_at: now,
|
|
205
|
+
last_accessed_at: now,
|
|
206
|
+
access_count: 0,
|
|
207
|
+
session_id: sessionId,
|
|
208
|
+
source,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Retrieve a single memory by ID, boosting its importance.
|
|
213
|
+
*/
|
|
214
|
+
getMemory(id) {
|
|
215
|
+
const row = this.stmtGetById.get(id);
|
|
216
|
+
if (!row)
|
|
217
|
+
return null;
|
|
218
|
+
// Boost on access
|
|
219
|
+
this.stmtBumpAccess.run(Date.now(), id);
|
|
220
|
+
// Re-read after boost
|
|
221
|
+
const updated = this.stmtGetById.get(id);
|
|
222
|
+
return this.rowToMemory(updated);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Update an existing memory.
|
|
226
|
+
*/
|
|
227
|
+
updateMemory(id, updates) {
|
|
228
|
+
const existing = this.stmtGetById.get(id);
|
|
229
|
+
if (!existing)
|
|
230
|
+
return null;
|
|
231
|
+
const now = Date.now();
|
|
232
|
+
this.stmtUpdate.run(updates.category ?? existing.category, updates.content ?? existing.content, updates.importance ?? existing.importance, JSON.stringify(updates.tags ?? JSON.parse(existing.tags)), JSON.stringify(updates.relatedFiles ?? JSON.parse(existing.related_files)), now, updates.sessionId ?? existing.session_id, updates.source ?? existing.source, id);
|
|
233
|
+
const updated = this.stmtGetById.get(id);
|
|
234
|
+
return this.rowToMemory(updated);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Delete a memory by ID.
|
|
238
|
+
*
|
|
239
|
+
* @returns `true` if the memory existed.
|
|
240
|
+
*/
|
|
241
|
+
deleteMemory(id) {
|
|
242
|
+
const info = this.stmtDelete.run(id);
|
|
243
|
+
return info.changes > 0;
|
|
244
|
+
}
|
|
245
|
+
// ────────────────────────────────────────────────────────────
|
|
246
|
+
// Retrieval
|
|
247
|
+
// ────────────────────────────────────────────────────────────
|
|
248
|
+
/**
|
|
249
|
+
* Query memories with optional FTS5 text search, category/tag filters,
|
|
250
|
+
* importance threshold, and token budget.
|
|
251
|
+
*
|
|
252
|
+
* Results are ranked by a composite score:
|
|
253
|
+
* 0.5 × textRelevance + 0.3 × importance + 0.2 × recency
|
|
254
|
+
*/
|
|
255
|
+
queryMemories(query) {
|
|
256
|
+
const limit = query.limit ?? 20;
|
|
257
|
+
let rows;
|
|
258
|
+
// ── FTS path ─────────────────────────────────────────────
|
|
259
|
+
if (query.text && query.text.trim().length > 0) {
|
|
260
|
+
const ftsQuery = this.buildFtsQuery(query.text);
|
|
261
|
+
try {
|
|
262
|
+
rows = this.stmtSearchFts.all(ftsQuery);
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// FTS query syntax error — fall back to LIKE search
|
|
266
|
+
rows = this.fallbackLikeSearch(query.text);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
rows = this.stmtAll.all();
|
|
271
|
+
}
|
|
272
|
+
// ── Post-filter ──────────────────────────────────────────
|
|
273
|
+
let memories = rows.map(r => this.rowToMemory(r));
|
|
274
|
+
if (query.categories && query.categories.length > 0) {
|
|
275
|
+
const set = new Set(query.categories);
|
|
276
|
+
memories = memories.filter(m => set.has(m.category));
|
|
277
|
+
}
|
|
278
|
+
if (query.tags && query.tags.length > 0) {
|
|
279
|
+
const tagSet = new Set(query.tags.map(t => t.toLowerCase()));
|
|
280
|
+
memories = memories.filter(m => m.tags.some(t => tagSet.has(t.toLowerCase())));
|
|
281
|
+
}
|
|
282
|
+
if (query.relatedFiles && query.relatedFiles.length > 0) {
|
|
283
|
+
const fileSet = new Set(query.relatedFiles.map(f => this.normalizePath(f)));
|
|
284
|
+
memories = memories.filter(m => m.relatedFiles.some(rf => fileSet.has(this.normalizePath(rf))));
|
|
285
|
+
}
|
|
286
|
+
if (query.minImportance !== undefined) {
|
|
287
|
+
memories = memories.filter(m => m.importance >= query.minImportance);
|
|
288
|
+
}
|
|
289
|
+
// ── Rank by composite score ──────────────────────────────
|
|
290
|
+
const now = Date.now();
|
|
291
|
+
const maxRank = rows.length > 0
|
|
292
|
+
? Math.max(...rows.map(r => Math.abs(r.rank ?? 0)), 1)
|
|
293
|
+
: 1;
|
|
294
|
+
memories.sort((a, b) => {
|
|
295
|
+
const scoreA = this.compositeScore(a, rows, maxRank, now);
|
|
296
|
+
const scoreB = this.compositeScore(b, rows, maxRank, now);
|
|
297
|
+
return scoreB - scoreA; // descending
|
|
298
|
+
});
|
|
299
|
+
// ── Apply limit ──────────────────────────────────────────
|
|
300
|
+
memories = memories.slice(0, limit);
|
|
301
|
+
// ── Apply token budget ───────────────────────────────────
|
|
302
|
+
if (query.tokenBudget !== undefined && query.tokenBudget > 0) {
|
|
303
|
+
memories = this.applyTokenBudget(memories, query.tokenBudget);
|
|
304
|
+
}
|
|
305
|
+
// ── Boost accessed memories ──────────────────────────────
|
|
306
|
+
const bumpTxn = this.db.transaction((ids) => {
|
|
307
|
+
const bumpNow = Date.now();
|
|
308
|
+
for (const id of ids) {
|
|
309
|
+
this.stmtBumpAccess.run(bumpNow, id);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
bumpTxn(memories.map(m => m.id));
|
|
313
|
+
return memories;
|
|
314
|
+
}
|
|
315
|
+
// ────────────────────────────────────────────────────────────
|
|
316
|
+
// Decay & Pruning
|
|
317
|
+
// ────────────────────────────────────────────────────────────
|
|
318
|
+
/**
|
|
319
|
+
* Apply time-based importance decay to all memories.
|
|
320
|
+
*
|
|
321
|
+
* Each memory's importance is multiplied by `decayRate ^ daysSinceLastAccess`.
|
|
322
|
+
* Call this periodically (e.g. once per session start).
|
|
323
|
+
*/
|
|
324
|
+
applyDecay() {
|
|
325
|
+
const now = Date.now();
|
|
326
|
+
const allRows = this.stmtAll.all();
|
|
327
|
+
let decayed = 0;
|
|
328
|
+
const txn = this.db.transaction(() => {
|
|
329
|
+
const updateStmt = this.db.prepare(`UPDATE memories SET importance = ? WHERE id = ?`);
|
|
330
|
+
for (const row of allRows) {
|
|
331
|
+
const lastAccessed = row.last_accessed_at;
|
|
332
|
+
const daysSince = (now - lastAccessed) / (1000 * 60 * 60 * 24);
|
|
333
|
+
if (daysSince < 0.01)
|
|
334
|
+
continue; // Skip very recent
|
|
335
|
+
const currentImportance = row.importance;
|
|
336
|
+
const newImportance = currentImportance * Math.pow(this.decayRate, daysSince);
|
|
337
|
+
if (Math.abs(newImportance - currentImportance) > 0.001) {
|
|
338
|
+
updateStmt.run(Math.max(0, newImportance), row.id);
|
|
339
|
+
decayed++;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
txn();
|
|
344
|
+
// Prune memories that fell below threshold
|
|
345
|
+
this.pruneIfNeeded();
|
|
346
|
+
return decayed;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Remove low-importance memories when capacity is exceeded.
|
|
350
|
+
*
|
|
351
|
+
* @returns Number of memories pruned.
|
|
352
|
+
*/
|
|
353
|
+
pruneIfNeeded() {
|
|
354
|
+
const countRow = this.stmtCount.get();
|
|
355
|
+
const excess = countRow.cnt - this.maxMemories;
|
|
356
|
+
if (excess <= 0)
|
|
357
|
+
return 0;
|
|
358
|
+
const toPrune = this.stmtPrunable.all(this.importanceThreshold, excess);
|
|
359
|
+
if (toPrune.length === 0)
|
|
360
|
+
return 0;
|
|
361
|
+
const txn = this.db.transaction(() => {
|
|
362
|
+
for (const { id } of toPrune) {
|
|
363
|
+
this.stmtDelete.run(id);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
txn();
|
|
367
|
+
return toPrune.length;
|
|
368
|
+
}
|
|
369
|
+
// ────────────────────────────────────────────────────────────
|
|
370
|
+
// Bulk Operations
|
|
371
|
+
// ────────────────────────────────────────────────────────────
|
|
372
|
+
/**
|
|
373
|
+
* Export all memories as a JSON-serializable array.
|
|
374
|
+
*/
|
|
375
|
+
exportMemories() {
|
|
376
|
+
const rows = this.stmtAll.all();
|
|
377
|
+
return rows.map(r => this.rowToMemory(r));
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Import memories from a JSON array.
|
|
381
|
+
*
|
|
382
|
+
* Deduplication is applied per memory. Existing memories are merged.
|
|
383
|
+
*
|
|
384
|
+
* @returns Number of memories imported (created + merged).
|
|
385
|
+
*/
|
|
386
|
+
importMemories(memories) {
|
|
387
|
+
let imported = 0;
|
|
388
|
+
const txn = this.db.transaction(() => {
|
|
389
|
+
for (const mem of memories) {
|
|
390
|
+
this.createMemory(mem);
|
|
391
|
+
imported++;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
txn();
|
|
395
|
+
return imported;
|
|
396
|
+
}
|
|
397
|
+
// ────────────────────────────────────────────────────────────
|
|
398
|
+
// Statistics
|
|
399
|
+
// ────────────────────────────────────────────────────────────
|
|
400
|
+
/** Aggregate statistics about the memory store. */
|
|
401
|
+
getStats() {
|
|
402
|
+
const countRow = this.stmtCount.get();
|
|
403
|
+
const avgRow = this.stmtAvgImportance.get();
|
|
404
|
+
const oldestRow = this.stmtOldest.get();
|
|
405
|
+
const newestRow = this.stmtNewest.get();
|
|
406
|
+
const totalAccessRow = this.stmtTotalAccess.get();
|
|
407
|
+
const catRows = this.stmtCategoryCount.all();
|
|
408
|
+
const byCategory = {};
|
|
409
|
+
for (const { category, cnt } of catRows) {
|
|
410
|
+
byCategory[category] = cnt;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
totalMemories: countRow.cnt,
|
|
414
|
+
byCategory,
|
|
415
|
+
averageImportance: avgRow.avg ?? 0,
|
|
416
|
+
oldestCreatedAt: oldestRow.ts,
|
|
417
|
+
newestCreatedAt: newestRow.ts,
|
|
418
|
+
totalAccessCount: totalAccessRow.total ?? 0,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
// ────────────────────────────────────────────────────────────
|
|
422
|
+
// Deduplication
|
|
423
|
+
// ────────────────────────────────────────────────────────────
|
|
424
|
+
/**
|
|
425
|
+
* Find an existing memory that's similar enough to be considered a duplicate.
|
|
426
|
+
*
|
|
427
|
+
* Uses Jaccard similarity on word sets with a threshold of 0.8.
|
|
428
|
+
*/
|
|
429
|
+
findDuplicate(content, category) {
|
|
430
|
+
// Only compare within same category for speed
|
|
431
|
+
const candidates = this.db
|
|
432
|
+
.prepare(`SELECT * FROM memories WHERE category = ?`)
|
|
433
|
+
.all(category);
|
|
434
|
+
const inputWords = this.tokenize(content);
|
|
435
|
+
const SIMILARITY_THRESHOLD = 0.8;
|
|
436
|
+
for (const row of candidates) {
|
|
437
|
+
const existingWords = this.tokenize(row.content);
|
|
438
|
+
const sim = this.jaccardSimilarity(inputWords, existingWords);
|
|
439
|
+
if (sim >= SIMILARITY_THRESHOLD) {
|
|
440
|
+
return row;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Merge new content into an existing memory.
|
|
447
|
+
*
|
|
448
|
+
* Strategy:
|
|
449
|
+
* - Content: keep longer text (or combine if meaningfully different)
|
|
450
|
+
* - Tags: union
|
|
451
|
+
* - Files: union
|
|
452
|
+
* - Importance: max
|
|
453
|
+
* - Bump access count
|
|
454
|
+
*/
|
|
455
|
+
mergeMemory(existing, input, now) {
|
|
456
|
+
const existingTags = JSON.parse(existing.tags);
|
|
457
|
+
const existingFiles = JSON.parse(existing.related_files);
|
|
458
|
+
const mergedTags = [...new Set([...existingTags, ...(input.tags ?? [])])];
|
|
459
|
+
const mergedFiles = [...new Set([...existingFiles, ...(input.relatedFiles ?? [])])];
|
|
460
|
+
// Keep the longer/more detailed content
|
|
461
|
+
const existingContent = existing.content;
|
|
462
|
+
const mergedContent = input.content.length > existingContent.length
|
|
463
|
+
? input.content
|
|
464
|
+
: existingContent;
|
|
465
|
+
const mergedImportance = Math.min(1.0, Math.max(existing.importance, input.importance ?? CATEGORY_IMPORTANCE[input.category] ?? 0.5) + 0.05);
|
|
466
|
+
const id = existing.id;
|
|
467
|
+
this.stmtUpdate.run(input.category, mergedContent, mergedImportance, JSON.stringify(mergedTags), JSON.stringify(mergedFiles), now, input.sessionId ?? existing.session_id, input.source ?? existing.source, id);
|
|
468
|
+
// Bump access
|
|
469
|
+
this.stmtBumpAccess.run(now, id);
|
|
470
|
+
const updated = this.stmtGetById.get(id);
|
|
471
|
+
return this.rowToMemory(updated);
|
|
472
|
+
}
|
|
473
|
+
// ────────────────────────────────────────────────────────────
|
|
474
|
+
// FTS Helpers
|
|
475
|
+
// ────────────────────────────────────────────────────────────
|
|
476
|
+
/**
|
|
477
|
+
* Sanitize user input for FTS5 query syntax.
|
|
478
|
+
*
|
|
479
|
+
* Wraps each word in quotes to avoid operators being misinterpreted.
|
|
480
|
+
*/
|
|
481
|
+
buildFtsQuery(text) {
|
|
482
|
+
const words = text
|
|
483
|
+
.replace(/[^\w\s]/g, ' ')
|
|
484
|
+
.split(/\s+/)
|
|
485
|
+
.filter(w => w.length > 0);
|
|
486
|
+
if (words.length === 0)
|
|
487
|
+
return '""';
|
|
488
|
+
// Join with OR for broader matching
|
|
489
|
+
return words.map(w => `"${w}"`).join(' OR ');
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Fallback search when FTS query fails (e.g. special characters).
|
|
493
|
+
*/
|
|
494
|
+
fallbackLikeSearch(text) {
|
|
495
|
+
const pattern = `%${text}%`;
|
|
496
|
+
return this.db
|
|
497
|
+
.prepare(`SELECT *, 0 AS rank FROM memories WHERE content LIKE ? ORDER BY importance DESC LIMIT 50`)
|
|
498
|
+
.all(pattern);
|
|
499
|
+
}
|
|
500
|
+
// ────────────────────────────────────────────────────────────
|
|
501
|
+
// Scoring & Token Budget
|
|
502
|
+
// ────────────────────────────────────────────────────────────
|
|
503
|
+
/**
|
|
504
|
+
* Compute composite relevance score for ranking.
|
|
505
|
+
*
|
|
506
|
+
* Score = 0.5 × textRelevance + 0.3 × importance + 0.2 × recency
|
|
507
|
+
*/
|
|
508
|
+
compositeScore(memory, rawRows, maxRank, now) {
|
|
509
|
+
// Text relevance (from BM25 rank — lower is more relevant)
|
|
510
|
+
const rawRow = rawRows.find(r => r.id === memory.id);
|
|
511
|
+
const rank = rawRow ? Math.abs(rawRow.rank ?? 0) : 0;
|
|
512
|
+
const textScore = maxRank > 0 ? 1 - rank / maxRank : 0;
|
|
513
|
+
// Recency (exponential decay over 30 days)
|
|
514
|
+
const daysSinceAccess = (now - memory.lastAccessedAt) / (1000 * 60 * 60 * 24);
|
|
515
|
+
const recencyScore = Math.exp(-daysSinceAccess / 30);
|
|
516
|
+
return 0.5 * textScore + 0.3 * memory.importance + 0.2 * recencyScore;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Trim the result set so total estimated tokens ≤ budget.
|
|
520
|
+
*/
|
|
521
|
+
applyTokenBudget(memories, budget) {
|
|
522
|
+
const result = [];
|
|
523
|
+
let usedTokens = 0;
|
|
524
|
+
for (const mem of memories) {
|
|
525
|
+
const estimatedTokens = Math.ceil(mem.content.length / CHARS_PER_TOKEN);
|
|
526
|
+
if (usedTokens + estimatedTokens > budget)
|
|
527
|
+
break;
|
|
528
|
+
result.push(mem);
|
|
529
|
+
usedTokens += estimatedTokens;
|
|
530
|
+
}
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
533
|
+
// ────────────────────────────────────────────────────────────
|
|
534
|
+
// Text Similarity Helpers
|
|
535
|
+
// ────────────────────────────────────────────────────────────
|
|
536
|
+
/** Tokenize content into a set of lowercase words. */
|
|
537
|
+
tokenize(text) {
|
|
538
|
+
return new Set(text
|
|
539
|
+
.toLowerCase()
|
|
540
|
+
.replace(/[^\w\s]/g, ' ')
|
|
541
|
+
.split(/\s+/)
|
|
542
|
+
.filter(w => w.length > 1));
|
|
543
|
+
}
|
|
544
|
+
/** Jaccard similarity between two word sets. */
|
|
545
|
+
jaccardSimilarity(a, b) {
|
|
546
|
+
if (a.size === 0 && b.size === 0)
|
|
547
|
+
return 1;
|
|
548
|
+
let intersection = 0;
|
|
549
|
+
for (const word of a) {
|
|
550
|
+
if (b.has(word))
|
|
551
|
+
intersection++;
|
|
552
|
+
}
|
|
553
|
+
const union = a.size + b.size - intersection;
|
|
554
|
+
return union === 0 ? 0 : intersection / union;
|
|
555
|
+
}
|
|
556
|
+
/** Normalize file paths for comparison. */
|
|
557
|
+
normalizePath(p) {
|
|
558
|
+
return p.replace(/\\/g, '/').toLowerCase();
|
|
559
|
+
}
|
|
560
|
+
// ────────────────────────────────────────────────────────────
|
|
561
|
+
// Row → Domain Object
|
|
562
|
+
// ────────────────────────────────────────────────────────────
|
|
563
|
+
rowToMemory(row) {
|
|
564
|
+
return {
|
|
565
|
+
id: row.id,
|
|
566
|
+
category: row.category,
|
|
567
|
+
content: row.content,
|
|
568
|
+
importance: row.importance,
|
|
569
|
+
tags: JSON.parse(row.tags || '[]'),
|
|
570
|
+
relatedFiles: JSON.parse(row.related_files || '[]'),
|
|
571
|
+
createdAt: row.created_at,
|
|
572
|
+
lastAccessedAt: row.last_accessed_at,
|
|
573
|
+
accessCount: row.access_count,
|
|
574
|
+
sessionId: row.session_id,
|
|
575
|
+
source: row.source,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
//# sourceMappingURL=persistent-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistent-memory.js","sourceRoot":"","sources":["../../src/memory/persistent-memory.ts"],"names":[],"mappings":"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"}
|