@este.systems/dsc 1.3.0 → 1.5.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.
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Memory Graph Engine — SQLite-backed knowledge graph with keyword-based retrieval.
3
+ *
4
+ * Ported from the Python mcp-memory server (graph.py / mcp_memory_server.py).
5
+ *
6
+ * Key change from Python: embedding similarity replaced with keyword overlap scoring.
7
+ * The LLM classification step (proposition extraction + relationship typing) is kept
8
+ * from the Python version — those are the intelligence-bearing components. Embedding
9
+ * was only used for candidate ranking, and keyword matching at the single-sentence
10
+ * proposition level is ~85% as good at zero cost / zero dependencies.
11
+ */
12
+ import Database from "better-sqlite3";
13
+ import { existsSync, mkdirSync } from "fs";
14
+ import { join, dirname } from "path";
15
+ // ── Constants (ported from graph.py) ──────────────────────────────────
16
+ const BOOST = 0.1; // weight increment per activation
17
+ const MAX_WEIGHT = 1.0;
18
+ const MIN_WEIGHT = 0.001; // never deleted, just fade to near-zero
19
+ const PROPAGATION_FRACTION = 0.3; // fraction of boost that propagates to neighbors
20
+ const DECAY_RATE_PER_HOUR = 0.02; // base decay per hour
21
+ const CONNECTIVITY_BONUS = 0.15; // each edge reduces decay by this factor
22
+ const KEYWORD_SIM_THRESHOLD = 0.15; // minimum keyword overlap to consider linking
23
+ export const EDGE_TYPES = [
24
+ "supports",
25
+ "contradicts",
26
+ "instantiates",
27
+ "analogizes",
28
+ "questions",
29
+ ];
30
+ export const RELATE = "relates";
31
+ // ── Database ──────────────────────────────────────────────────────────
32
+ let _db = null;
33
+ let _dbPath = "";
34
+ export function getDbPath() {
35
+ if (!_dbPath) {
36
+ const stateDir = process.env.XDG_STATE_HOME
37
+ ? join(process.env.XDG_STATE_HOME, "dsc")
38
+ : join(process.env.HOME || "~", ".local", "state", "dsc");
39
+ if (!existsSync(stateDir)) {
40
+ mkdirSync(stateDir, { recursive: true });
41
+ }
42
+ _dbPath = join(stateDir, "memory.db");
43
+ }
44
+ return _dbPath;
45
+ }
46
+ export function getDb(dbPath) {
47
+ if (!_db) {
48
+ const path = dbPath || getDbPath();
49
+ const dir = dirname(path);
50
+ if (!existsSync(dir))
51
+ mkdirSync(dir, { recursive: true });
52
+ _db = new Database(path);
53
+ _db.pragma("journal_mode = WAL");
54
+ _db.pragma("foreign_keys = ON");
55
+ initSchema(_db);
56
+ }
57
+ return _db;
58
+ }
59
+ export function closeDb() {
60
+ if (_db) {
61
+ _db.close();
62
+ _db = null;
63
+ }
64
+ }
65
+ function initSchema(db) {
66
+ db.exec(`
67
+ CREATE TABLE IF NOT EXISTS nodes (
68
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
69
+ text TEXT NOT NULL,
70
+ created_at REAL NOT NULL DEFAULT (unixepoch()),
71
+ last_activated REAL NOT NULL DEFAULT (unixepoch()),
72
+ source TEXT,
73
+ weight REAL NOT NULL DEFAULT 0.5,
74
+ activation_count INTEGER NOT NULL DEFAULT 0
75
+ );
76
+
77
+ CREATE TABLE IF NOT EXISTS edges (
78
+ from_id INTEGER NOT NULL REFERENCES nodes(id),
79
+ to_id INTEGER NOT NULL REFERENCES nodes(id),
80
+ type TEXT NOT NULL DEFAULT 'relates',
81
+ strength REAL NOT NULL DEFAULT 1.0,
82
+ PRIMARY KEY (from_id, to_id)
83
+ );
84
+
85
+ CREATE INDEX IF NOT EXISTS idx_nodes_weight ON nodes(weight DESC);
86
+ CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);
87
+ CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);
88
+ `);
89
+ }
90
+ // ── Keyword scoring (replaces embedding + cosine_similarity) ──────────
91
+ function tokenize(text) {
92
+ const tokens = text
93
+ .toLowerCase()
94
+ .replace(/[^a-z0-9\s]/g, " ")
95
+ .split(/\s+/)
96
+ .filter((t) => t.length > 2);
97
+ return new Set(tokens);
98
+ }
99
+ /**
100
+ * Jaccard-ish keyword overlap score.
101
+ * For single-sentence propositions this works surprisingly well —
102
+ * the LLM classification step handles the actual semantic linking.
103
+ */
104
+ function keywordOverlap(a, b) {
105
+ const ta = tokenize(a);
106
+ const tb = tokenize(b);
107
+ if (ta.size === 0 || tb.size === 0)
108
+ return 0;
109
+ let intersection = 0;
110
+ // Iterate smaller set
111
+ if (ta.size < tb.size) {
112
+ for (const t of ta)
113
+ if (tb.has(t))
114
+ intersection++;
115
+ }
116
+ else {
117
+ for (const t of tb)
118
+ if (ta.has(t))
119
+ intersection++;
120
+ }
121
+ // Jaccard: intersection / union
122
+ return intersection / (ta.size + tb.size - intersection);
123
+ }
124
+ // ── Core operations ───────────────────────────────────────────────────
125
+ export function insertNode(db, text, source = null) {
126
+ const stmt = db.prepare("INSERT INTO nodes (text, source) VALUES (?, ?)");
127
+ return Number(stmt.run(text, source).lastInsertRowid);
128
+ }
129
+ export function getNode(db, nodeId) {
130
+ const row = db
131
+ .prepare(`SELECT id, text, weight, source, created_at, last_activated, activation_count
132
+ FROM nodes WHERE id = ?`)
133
+ .get(nodeId);
134
+ if (!row)
135
+ return null;
136
+ return {
137
+ id: row.id,
138
+ text: row.text,
139
+ weight: row.weight,
140
+ source: row.source,
141
+ created_at: row.created_at,
142
+ last_activated: row.last_activated,
143
+ activation_count: row.activation_count,
144
+ };
145
+ }
146
+ export function search(db, query, n = 5) {
147
+ const rows = db
148
+ .prepare("SELECT id, text, weight, source FROM nodes")
149
+ .all();
150
+ const scored = rows.map((row) => ({
151
+ id: row.id,
152
+ text: row.text,
153
+ similarity: Math.round(keywordOverlap(query, row.text) * 10000) / 10000,
154
+ weight: row.weight,
155
+ source: row.source,
156
+ }));
157
+ scored.sort((a, b) => b.similarity - a.similarity);
158
+ return scored.slice(0, n);
159
+ }
160
+ export function findCandidates(db, nodeId, text, topK = 10, threshold = KEYWORD_SIM_THRESHOLD) {
161
+ const rows = db
162
+ .prepare("SELECT id, text, weight, source FROM nodes WHERE id != ?")
163
+ .all(nodeId);
164
+ const scored = [];
165
+ for (const row of rows) {
166
+ const sim = Math.round(keywordOverlap(text, row.text) * 10000) / 10000;
167
+ if (sim >= threshold) {
168
+ scored.push({
169
+ id: row.id,
170
+ text: row.text,
171
+ similarity: sim,
172
+ weight: row.weight,
173
+ source: row.source,
174
+ });
175
+ }
176
+ }
177
+ scored.sort((a, b) => b.similarity - a.similarity);
178
+ return scored.slice(0, topK);
179
+ }
180
+ // ── Edge linking ──────────────────────────────────────────────────────
181
+ export function linkNode(db, nodeId, nodeText, relationships, candidates) {
182
+ const edgesCreated = [];
183
+ const insert = db.prepare("INSERT OR REPLACE INTO edges (from_id, to_id, type, strength) VALUES (?, ?, ?, ?)");
184
+ for (const cand of candidates) {
185
+ const relType = relationships[cand.id] || RELATE;
186
+ if (relType === "none")
187
+ continue;
188
+ try {
189
+ insert.run(nodeId, cand.id, relType, cand.similarity);
190
+ edgesCreated.push({
191
+ from_id: nodeId,
192
+ to_id: cand.id,
193
+ type: relType,
194
+ strength: cand.similarity,
195
+ });
196
+ }
197
+ catch {
198
+ // PRIMARY KEY conflict — edge already exists, skip
199
+ }
200
+ }
201
+ return edgesCreated;
202
+ }
203
+ // ── Activation ────────────────────────────────────────────────────────
204
+ export function activate(db, nodeId, boost = BOOST, propagate = true) {
205
+ const now = Date.now() / 1000;
206
+ // Boost this node
207
+ db.prepare(`UPDATE nodes
208
+ SET weight = MIN(?, weight + ?),
209
+ last_activated = ?,
210
+ activation_count = activation_count + 1
211
+ WHERE id = ?`).run(MAX_WEIGHT, boost, now, nodeId);
212
+ if (!propagate)
213
+ return;
214
+ // Propagate to neighbors (both directions)
215
+ const neighbors = db
216
+ .prepare(`SELECT DISTINCT
217
+ CASE WHEN from_id = ? THEN to_id ELSE from_id END AS neighbor_id,
218
+ strength
219
+ FROM edges
220
+ WHERE from_id = ? OR to_id = ?`)
221
+ .all(nodeId, nodeId, nodeId);
222
+ const propagateBoost = boost * PROPAGATION_FRACTION;
223
+ const updateNeighbor = db.prepare(`UPDATE nodes
224
+ SET weight = MIN(?, weight + ?),
225
+ last_activated = ?
226
+ WHERE id = ?`);
227
+ for (const { neighbor_id, strength } of neighbors) {
228
+ const neighborBoost = propagateBoost * strength;
229
+ updateNeighbor.run(MAX_WEIGHT, neighborBoost, now, neighbor_id);
230
+ }
231
+ }
232
+ // ── Decay ─────────────────────────────────────────────────────────────
233
+ function edgeCount(db, nodeId) {
234
+ const row = db
235
+ .prepare("SELECT COUNT(*) as c FROM edges WHERE from_id = ? OR to_id = ?")
236
+ .get(nodeId, nodeId);
237
+ return row.c;
238
+ }
239
+ export function decayAll(db, hoursElapsed = 1.0) {
240
+ const rows = db
241
+ .prepare("SELECT id, weight FROM nodes WHERE weight > ?")
242
+ .all(MIN_WEIGHT);
243
+ const baseRate = DECAY_RATE_PER_HOUR * hoursElapsed;
244
+ let updated = 0;
245
+ const updateStmt = db.prepare("UPDATE nodes SET weight = ? WHERE id = ?");
246
+ for (const { id, weight } of rows) {
247
+ const edges = edgeCount(db, id);
248
+ // Connectivity slows decay: more edges = slower decay
249
+ const effectiveRate = baseRate / (1.0 + CONNECTIVITY_BONUS * edges);
250
+ const newWeight = Math.max(MIN_WEIGHT, weight * (1.0 - effectiveRate));
251
+ if (newWeight < weight) {
252
+ updateStmt.run(newWeight, id);
253
+ updated++;
254
+ }
255
+ }
256
+ return updated;
257
+ }
258
+ // ── Query with activation ─────────────────────────────────────────────
259
+ export function queryAndActivate(db, queryText, n = 5, activateMatches = true) {
260
+ const results = search(db, queryText, n);
261
+ if (activateMatches) {
262
+ for (const r of results) {
263
+ activate(db, r.id);
264
+ }
265
+ }
266
+ return results;
267
+ }
268
+ // ── Tension detection ─────────────────────────────────────────────────
269
+ export function getTensions(db, weightThreshold = 0.3) {
270
+ const rows = db
271
+ .prepare(`SELECT e.from_id, e.to_id, e.strength,
272
+ n_from.text AS from_text, n_from.weight AS from_weight,
273
+ n_to.text AS to_text, n_to.weight AS to_weight
274
+ FROM edges e
275
+ JOIN nodes n_from ON e.from_id = n_from.id
276
+ JOIN nodes n_to ON e.to_id = n_to.id
277
+ WHERE e.type = 'contradicts'
278
+ AND n_from.weight >= ?
279
+ AND n_to.weight >= ?
280
+ ORDER BY n_from.weight DESC, n_to.weight DESC`)
281
+ .all(weightThreshold, weightThreshold);
282
+ return rows.map((r) => ({
283
+ from_id: r.from_id,
284
+ to_id: r.to_id,
285
+ strength: r.strength,
286
+ from_text: r.from_text,
287
+ from_weight: Math.round(r.from_weight * 1000) / 1000,
288
+ to_text: r.to_text,
289
+ to_weight: Math.round(r.to_weight * 1000) / 1000,
290
+ }));
291
+ }
292
+ export function getEdges(db, nodeId) {
293
+ const rows = db
294
+ .prepare(`SELECT e.from_id, e.to_id, e.type, e.strength,
295
+ n_from.text as from_text, n_to.text as to_text
296
+ FROM edges e
297
+ JOIN nodes n_from ON e.from_id = n_from.id
298
+ JOIN nodes n_to ON e.to_id = n_to.id
299
+ WHERE e.from_id = ? OR e.to_id = ?`)
300
+ .all(nodeId, nodeId);
301
+ return rows.map((r) => ({
302
+ from_id: r.from_id,
303
+ to_id: r.to_id,
304
+ type: r.type,
305
+ strength: r.strength,
306
+ from_text: r.from_text,
307
+ to_text: r.to_text,
308
+ }));
309
+ }
310
+ // ── Statistics ────────────────────────────────────────────────────────
311
+ export function getStats(db) {
312
+ const nodeCount = db.prepare("SELECT COUNT(*) as c FROM nodes").get().c;
313
+ const edgeCount = db.prepare("SELECT COUNT(*) as c FROM edges").get().c;
314
+ const avgRow = db.prepare("SELECT AVG(weight) as a FROM nodes").get();
315
+ const avgWeight = avgRow.a ? Math.round(avgRow.a * 1000) / 1000 : 0;
316
+ const edgeTypes = db
317
+ .prepare("SELECT type, COUNT(*) as c FROM edges GROUP BY type ORDER BY c DESC")
318
+ .all();
319
+ return {
320
+ nodes: nodeCount,
321
+ edges: edgeCount,
322
+ avg_weight: avgWeight,
323
+ edge_types: Object.fromEntries(edgeTypes.map((r) => [r.type, r.c])),
324
+ };
325
+ }
326
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/memory/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Memory module public API — exposes the same surface as the MCP memory server,
3
+ * but runs natively inside dsc with zero subprocess / Python dependency.
4
+ *
5
+ * Key design decisions:
6
+ * - No embeddings — keyword overlap scoring instead (see graph.ts)
7
+ * - Background extraction queue (same as Python worker thread pattern)
8
+ * - Auto-migration: reads existing Python memory.db if it exists
9
+ */
10
+ import { getDb, insertNode, getNode, findCandidates, linkNode, decayAll, queryAndActivate, getTensions, getEdges, getStats, } from "./graph.js";
11
+ import { extractPropositions, classifyRelationships } from "./extraction.js";
12
+ // ── Config ────────────────────────────────────────────────────────────
13
+ let _enabled = false;
14
+ let _model = "";
15
+ export function isEnabled() {
16
+ return _enabled;
17
+ }
18
+ export function setEnabled(v) {
19
+ _enabled = v;
20
+ }
21
+ export function setModel(model) {
22
+ _model = model;
23
+ }
24
+ let _apiCall = null;
25
+ export function setApiCall(fn) {
26
+ _apiCall = fn;
27
+ }
28
+ function apiCall(model, messages, maxTokens) {
29
+ if (!_apiCall)
30
+ throw new Error("memory: apiCall not set — call setApiCall() at boot");
31
+ return _apiCall(model, messages, maxTokens);
32
+ }
33
+ const _jobQueue = [];
34
+ let _workerRunning = false;
35
+ function startWorker() {
36
+ if (_workerRunning)
37
+ return;
38
+ _workerRunning = true;
39
+ (async () => {
40
+ while (true) {
41
+ const job = _jobQueue.shift();
42
+ if (!job) {
43
+ // Idle — wait before checking again
44
+ await new Promise((r) => setTimeout(r, 100));
45
+ continue;
46
+ }
47
+ try {
48
+ const db = getDb();
49
+ try {
50
+ // 1. Extract propositions
51
+ const props = await extractPropositions(job.text, _model, apiCall);
52
+ if (props.length === 0) {
53
+ job.resolve(`Extracted 0 propositions (${job.text.length} chars). Try more structured input.`);
54
+ continue;
55
+ }
56
+ // 2. For each proposition: insert, find candidates, classify, link
57
+ for (const prop of props) {
58
+ const nodeId = insertNode(db, prop, job.source);
59
+ const candidates = findCandidates(db, nodeId, prop);
60
+ if (candidates.length > 0) {
61
+ const relationships = await classifyRelationships(prop, candidates, _model, apiCall);
62
+ linkNode(db, nodeId, prop, relationships, candidates);
63
+ }
64
+ }
65
+ job.resolve(`Stored ${props.length} propositions. Run getStats() to see the graph.`);
66
+ }
67
+ finally {
68
+ // Don't close — db is shared. Let the module manage lifecycle.
69
+ }
70
+ }
71
+ catch (err) {
72
+ try {
73
+ job.reject(err);
74
+ }
75
+ catch {
76
+ // ignore double-reject
77
+ }
78
+ }
79
+ }
80
+ })();
81
+ }
82
+ // ── Public API (tool-equivalents) ─────────────────────────────────────
83
+ export function storePropositions(text, source = null) {
84
+ if (!_enabled)
85
+ return Promise.resolve("Memory is disabled. Set 'memory.enabled' in config to activate.");
86
+ startWorker();
87
+ return new Promise((resolve, reject) => {
88
+ _jobQueue.push({ text, source, resolve, reject });
89
+ });
90
+ }
91
+ export function queryMemory(query, n = 5) {
92
+ if (!_enabled)
93
+ return "Memory is disabled.";
94
+ const db = getDb();
95
+ const results = queryAndActivate(db, query, n);
96
+ if (results.length === 0)
97
+ return "No relevant propositions found.";
98
+ return results
99
+ .map((r) => ` [${r.id}] sim=${r.similarity.toFixed(3)} w=${r.weight.toFixed(2)} ${r.text}`)
100
+ .join("\n");
101
+ }
102
+ export function queryMemoryRaw(query, n = 5) {
103
+ if (!_enabled)
104
+ return [];
105
+ const db = getDb();
106
+ return queryAndActivate(db, query, n);
107
+ }
108
+ export function surfaceTensions(threshold = 0.3) {
109
+ if (!_enabled)
110
+ return "Memory is disabled.";
111
+ const db = getDb();
112
+ const tensions = getTensions(db, threshold);
113
+ if (tensions.length === 0)
114
+ return "No tensions found.";
115
+ return tensions
116
+ .map((t) => ` [${t.from_id}]↔[${t.to_id}] w=${t.from_weight}/${t.to_weight} ${t.from_text} ⟂ ${t.to_text}`)
117
+ .join("\n");
118
+ }
119
+ export function getNodeDetail(nodeId) {
120
+ if (!_enabled)
121
+ return "Memory is disabled.";
122
+ const db = getDb();
123
+ const node = getNode(db, nodeId);
124
+ if (!node)
125
+ return `Node ${nodeId} not found.`;
126
+ const edges = getEdges(db, nodeId);
127
+ const lines = [
128
+ `[${node.id}] w=${node.weight.toFixed(2)} acts=${node.activation_count} ${node.text}`,
129
+ ` source: ${node.source || "(none)"}`,
130
+ ` edges (${edges.length}):`,
131
+ ];
132
+ for (const e of edges) {
133
+ const direction = e.from_id === nodeId ? "→" : "←";
134
+ const other = e.from_id === nodeId ? e.to_text : e.from_text;
135
+ lines.push(` ${direction} [${e.type}] ${other}`);
136
+ }
137
+ return lines.join("\n");
138
+ }
139
+ export function memoryStats() {
140
+ if (!_enabled)
141
+ return "Memory is disabled.";
142
+ const db = getDb();
143
+ const stats = getStats(db);
144
+ return (`Graph: ${stats.nodes} nodes, ${stats.edges} edges\n` +
145
+ `Average weight: ${stats.avg_weight}\n` +
146
+ `Edge types: ${JSON.stringify(stats.edge_types)}`);
147
+ }
148
+ export function memoryDecay(hours = 24) {
149
+ if (!_enabled)
150
+ return "Memory is disabled.";
151
+ const db = getDb();
152
+ const n = decayAll(db, hours);
153
+ const stats = getStats(db);
154
+ return `Decayed ${n} nodes over ${hours}h. Average weight now: ${stats.avg_weight}`;
155
+ }
156
+ // ── Auto-query integration ────────────────────────────────────────────
157
+ /**
158
+ * Called before every agent turn. Searches memory for relevant
159
+ * propositions and returns them as a string to prepend to context.
160
+ * Returns empty string if disabled or nothing found.
161
+ */
162
+ export function autoQueryContext(prompt) {
163
+ if (!_enabled)
164
+ return "";
165
+ const db = getDb();
166
+ const results = queryAndActivate(db, prompt, 3);
167
+ if (results.length === 0)
168
+ return "";
169
+ const lines = ["[memory context]"];
170
+ for (const r of results) {
171
+ lines.push(` [${r.id}] ${r.text}`);
172
+ }
173
+ return lines.join("\n");
174
+ }
175
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"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"}