@jungjaehoon/mama-core 1.1.5 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/db/migrations/013-replace-vss-with-embeddings.sql +12 -0
- package/dist/config-loader.d.ts +6 -0
- package/dist/config-loader.js +9 -0
- package/dist/db-adapter/sqlite-adapter.d.ts +11 -4
- package/dist/db-adapter/sqlite-adapter.js +77 -84
- package/dist/db-manager.d.ts +3 -4
- package/dist/db-manager.js +4 -5
- package/dist/decision-tracker.d.ts +1 -1
- package/dist/decision-tracker.js +2 -2
- package/dist/embeddings.d.ts +2 -2
- package/dist/embeddings.js +7 -3
- package/dist/mama-api.js +1 -1
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ const mamaApi = require('@jungjaehoon/mama-core/mama-api');
|
|
|
108
108
|
|
|
109
109
|
- **@huggingface/transformers** - Local embedding generation
|
|
110
110
|
- **better-sqlite3** - SQLite database
|
|
111
|
-
- **
|
|
111
|
+
- **Pure-TS cosine similarity** - Vector search (no native extensions)
|
|
112
112
|
|
|
113
113
|
## Development
|
|
114
114
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Migration 013: Replace vss_memories (sqlite-vec virtual table) with plain embeddings table
|
|
2
|
+
-- Vector search now uses pure TypeScript brute-force cosine similarity.
|
|
3
|
+
-- No native extensions required.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
6
|
+
rowid INTEGER PRIMARY KEY,
|
|
7
|
+
embedding BLOB NOT NULL
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
-- Note: Data migration from vss_memories is handled programmatically in sqlite-adapter.ts
|
|
11
|
+
-- because vss_memories is a vec0 virtual table that requires sqlite-vec to read.
|
|
12
|
+
-- If sqlite-vec is available at migration time, the adapter will copy rows automatically.
|
package/dist/config-loader.d.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
export interface MAMAConfig {
|
|
16
16
|
modelName: string;
|
|
17
17
|
embeddingDim: number;
|
|
18
|
+
quantized: boolean;
|
|
18
19
|
cacheDir: string;
|
|
19
20
|
[key: string]: unknown;
|
|
20
21
|
}
|
|
@@ -36,6 +37,10 @@ export declare function getModelName(): string;
|
|
|
36
37
|
* Get current embedding dimension
|
|
37
38
|
*/
|
|
38
39
|
export declare function getEmbeddingDim(): number;
|
|
40
|
+
/**
|
|
41
|
+
* Get whether to use quantized model
|
|
42
|
+
*/
|
|
43
|
+
export declare function getQuantized(): boolean;
|
|
39
44
|
/**
|
|
40
45
|
* Get current cache directory
|
|
41
46
|
*/
|
|
@@ -43,6 +48,7 @@ export declare function getCacheDir(): string;
|
|
|
43
48
|
export interface ConfigUpdates {
|
|
44
49
|
modelName?: string;
|
|
45
50
|
embeddingDim?: number;
|
|
51
|
+
quantized?: boolean;
|
|
46
52
|
cacheDir?: string;
|
|
47
53
|
}
|
|
48
54
|
/**
|
package/dist/config-loader.js
CHANGED
|
@@ -21,6 +21,7 @@ exports.DEFAULT_CONFIG = void 0;
|
|
|
21
21
|
exports.loadConfig = loadConfig;
|
|
22
22
|
exports.getModelName = getModelName;
|
|
23
23
|
exports.getEmbeddingDim = getEmbeddingDim;
|
|
24
|
+
exports.getQuantized = getQuantized;
|
|
24
25
|
exports.getCacheDir = getCacheDir;
|
|
25
26
|
exports.updateConfig = updateConfig;
|
|
26
27
|
exports.getConfigPath = getConfigPath;
|
|
@@ -32,6 +33,7 @@ const debug_logger_js_1 = require("./debug-logger.js");
|
|
|
32
33
|
exports.DEFAULT_CONFIG = {
|
|
33
34
|
modelName: 'Xenova/multilingual-e5-small',
|
|
34
35
|
embeddingDim: 384,
|
|
36
|
+
quantized: true,
|
|
35
37
|
cacheDir: path_1.default.join(os_1.default.homedir(), '.cache', 'huggingface', 'transformers'),
|
|
36
38
|
};
|
|
37
39
|
// Config file path
|
|
@@ -129,6 +131,13 @@ function getEmbeddingDim() {
|
|
|
129
131
|
const config = loadConfig();
|
|
130
132
|
return config.embeddingDim;
|
|
131
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Get whether to use quantized model
|
|
136
|
+
*/
|
|
137
|
+
function getQuantized() {
|
|
138
|
+
const config = loadConfig();
|
|
139
|
+
return config.quantized;
|
|
140
|
+
}
|
|
132
141
|
/**
|
|
133
142
|
* Get current cache directory
|
|
134
143
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SQLite Database Adapter
|
|
3
3
|
*
|
|
4
|
-
* Implements DatabaseAdapter interface using better-sqlite3
|
|
5
|
-
*
|
|
4
|
+
* Implements DatabaseAdapter interface using better-sqlite3
|
|
5
|
+
* Vector search uses pure TypeScript brute-force cosine similarity (no native extensions)
|
|
6
6
|
*
|
|
7
7
|
* @module sqlite-adapter
|
|
8
8
|
*/
|
|
@@ -53,11 +53,13 @@ export declare class SQLiteAdapter extends DatabaseAdapter {
|
|
|
53
53
|
*/
|
|
54
54
|
transaction<T>(fn: () => T): T;
|
|
55
55
|
/**
|
|
56
|
-
* Vector similarity search using
|
|
56
|
+
* Vector similarity search using brute-force cosine similarity
|
|
57
|
+
* Loads all embeddings from the embeddings table, computes similarity in JS,
|
|
58
|
+
* and returns top-N results sorted by similarity descending.
|
|
57
59
|
*/
|
|
58
60
|
vectorSearch(embedding: Float32Array | number[], limit?: number): VectorSearchResult[] | null;
|
|
59
61
|
/**
|
|
60
|
-
* Insert vector embedding
|
|
62
|
+
* Insert vector embedding into the embeddings table (plain BLOB storage)
|
|
61
63
|
*/
|
|
62
64
|
insertEmbedding(rowid: number, embedding: Float32Array | number[]): RunResult | null;
|
|
63
65
|
/**
|
|
@@ -68,6 +70,11 @@ export declare class SQLiteAdapter extends DatabaseAdapter {
|
|
|
68
70
|
* Run migrations
|
|
69
71
|
*/
|
|
70
72
|
runMigrations(migrationsDir: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Attempt to migrate data from legacy vss_memories (sqlite-vec) to embeddings table.
|
|
75
|
+
* This is best-effort: if sqlite-vec is not loaded, the vss_memories table won't be readable.
|
|
76
|
+
*/
|
|
77
|
+
private _migrateFromVssMemories;
|
|
71
78
|
}
|
|
72
79
|
export default SQLiteAdapter;
|
|
73
80
|
//# sourceMappingURL=sqlite-adapter.d.ts.map
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* SQLite Database Adapter
|
|
4
4
|
*
|
|
5
|
-
* Implements DatabaseAdapter interface using better-sqlite3
|
|
6
|
-
*
|
|
5
|
+
* Implements DatabaseAdapter interface using better-sqlite3
|
|
6
|
+
* Vector search uses pure TypeScript brute-force cosine similarity (no native extensions)
|
|
7
7
|
*
|
|
8
8
|
* @module sqlite-adapter
|
|
9
9
|
*/
|
|
@@ -20,16 +20,6 @@ const base_adapter_js_1 = require("./base-adapter.js");
|
|
|
20
20
|
const statement_js_1 = require("./statement.js");
|
|
21
21
|
const debug_logger_js_1 = require("../debug-logger.js");
|
|
22
22
|
const embeddings_js_1 = require("../embeddings.js");
|
|
23
|
-
// Try to load sqlite-vec
|
|
24
|
-
let sqliteVec = null;
|
|
25
|
-
try {
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
-
sqliteVec = require('sqlite-vec');
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
// Defer logging until connect() so we have logger context initialized
|
|
31
|
-
sqliteVec = null;
|
|
32
|
-
}
|
|
33
23
|
// Database paths
|
|
34
24
|
const LEGACY_DB_PATH = path_1.default.join(os_1.default.homedir(), '.spinelift', 'memories.db');
|
|
35
25
|
// Default to ~/.claude/mama-memory.db for Claude Code/Desktop compatibility
|
|
@@ -37,7 +27,7 @@ const DEFAULT_DB_PATH = path_1.default.join(os_1.default.homedir(), '.claude', '
|
|
|
37
27
|
class SQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
38
28
|
config;
|
|
39
29
|
db = null;
|
|
40
|
-
_vectorSearchEnabled =
|
|
30
|
+
_vectorSearchEnabled = true; // Always true: pure TS cosine similarity
|
|
41
31
|
constructor(config = {}) {
|
|
42
32
|
super();
|
|
43
33
|
this.config = config;
|
|
@@ -93,23 +83,7 @@ class SQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
93
83
|
this.db.pragma('cache_size = -64000'); // 64MB cache
|
|
94
84
|
this.db.pragma('temp_store = MEMORY');
|
|
95
85
|
this.db.pragma('foreign_keys = ON');
|
|
96
|
-
|
|
97
|
-
if (sqliteVec) {
|
|
98
|
-
try {
|
|
99
|
-
sqliteVec.load(this.db);
|
|
100
|
-
this._vectorSearchEnabled = true;
|
|
101
|
-
(0, debug_logger_js_1.info)('[sqlite-adapter] Loaded sqlite-vec extension');
|
|
102
|
-
}
|
|
103
|
-
catch (err) {
|
|
104
|
-
this._vectorSearchEnabled = false;
|
|
105
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
106
|
-
(0, debug_logger_js_1.warn)(`[sqlite-adapter] sqlite-vec unavailable (Tier 2 fallback): ${message}`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
this._vectorSearchEnabled = false;
|
|
111
|
-
(0, debug_logger_js_1.warn)('[sqlite-adapter] sqlite-vec package not installed; vector search disabled');
|
|
112
|
-
}
|
|
86
|
+
(0, debug_logger_js_1.info)('[sqlite-adapter] Vector search: pure TS cosine similarity (no native extensions)');
|
|
113
87
|
return this.db;
|
|
114
88
|
}
|
|
115
89
|
/**
|
|
@@ -158,64 +132,55 @@ class SQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
158
132
|
return txn();
|
|
159
133
|
}
|
|
160
134
|
/**
|
|
161
|
-
* Vector similarity search using
|
|
135
|
+
* Vector similarity search using brute-force cosine similarity
|
|
136
|
+
* Loads all embeddings from the embeddings table, computes similarity in JS,
|
|
137
|
+
* and returns top-N results sorted by similarity descending.
|
|
162
138
|
*/
|
|
163
139
|
vectorSearch(embedding, limit = 5) {
|
|
164
140
|
if (!this.isConnected()) {
|
|
165
141
|
throw new Error('Database not connected');
|
|
166
142
|
}
|
|
167
|
-
if (!this._vectorSearchEnabled) {
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
const embeddingJson = JSON.stringify(Array.from(embedding));
|
|
171
|
-
const stmt = this.prepare(`
|
|
172
|
-
SELECT
|
|
173
|
-
rowid,
|
|
174
|
-
embedding,
|
|
175
|
-
distance
|
|
176
|
-
FROM vss_memories
|
|
177
|
-
WHERE embedding MATCH vec_f32(?)
|
|
178
|
-
LIMIT ?
|
|
179
|
-
`);
|
|
180
143
|
const queryVector = embedding instanceof Float32Array ? embedding : Float32Array.from(embedding);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
144
|
+
// Check if embeddings table exists
|
|
145
|
+
const tableCheck = this.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='embeddings'`).all();
|
|
146
|
+
if (tableCheck.length === 0) {
|
|
147
|
+
throw new Error('Embeddings table missing');
|
|
148
|
+
}
|
|
149
|
+
const rows = this.prepare('SELECT rowid, embedding FROM embeddings').all();
|
|
150
|
+
const scored = [];
|
|
151
|
+
for (const row of rows) {
|
|
184
152
|
const candidate = bufferToVector(row.embedding);
|
|
185
|
-
if (!candidate)
|
|
186
|
-
|
|
153
|
+
if (!candidate)
|
|
154
|
+
continue;
|
|
155
|
+
if (candidate.length !== queryVector.length) {
|
|
156
|
+
(0, debug_logger_js_1.warn)(`Skipping rowid ${row.rowid}: dimension mismatch (${candidate.length} vs ${queryVector.length})`);
|
|
157
|
+
continue;
|
|
187
158
|
}
|
|
188
159
|
const similarity = (0, embeddings_js_1.cosineSimilarity)(candidate, queryVector);
|
|
189
|
-
|
|
160
|
+
scored.push({
|
|
190
161
|
rowid: row.rowid,
|
|
191
162
|
similarity,
|
|
192
163
|
distance: 1 - similarity,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Sort by similarity descending, return top-N
|
|
167
|
+
scored.sort((a, b) => (b.similarity ?? 0) - (a.similarity ?? 0));
|
|
168
|
+
return scored.slice(0, Math.max(limit, 1));
|
|
196
169
|
}
|
|
197
170
|
/**
|
|
198
|
-
* Insert vector embedding
|
|
171
|
+
* Insert vector embedding into the embeddings table (plain BLOB storage)
|
|
199
172
|
*/
|
|
200
173
|
insertEmbedding(rowid, embedding) {
|
|
201
174
|
if (!this.isConnected()) {
|
|
202
175
|
throw new Error('Database not connected');
|
|
203
176
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
const embeddingJson = JSON.stringify(Array.from(embedding));
|
|
208
|
-
// CRITICAL FIX: sqlite-vec virtual tables accept rowid as literal but not via ? placeholder
|
|
209
|
-
// Using template literal with Number() cast for safety (prevents SQL injection)
|
|
210
|
-
const safeRowid = Number(rowid);
|
|
211
|
-
if (!Number.isInteger(safeRowid) || safeRowid < 1) {
|
|
212
|
-
throw new Error(`Invalid rowid: ${rowid}`);
|
|
213
|
-
}
|
|
177
|
+
const vec = embedding instanceof Float32Array ? embedding : Float32Array.from(embedding);
|
|
178
|
+
const buffer = Buffer.from(vec.buffer, vec.byteOffset, vec.byteLength);
|
|
214
179
|
const stmt = this.prepare(`
|
|
215
|
-
INSERT OR REPLACE INTO
|
|
216
|
-
VALUES (
|
|
180
|
+
INSERT OR REPLACE INTO embeddings(rowid, embedding)
|
|
181
|
+
VALUES (?, ?)
|
|
217
182
|
`);
|
|
218
|
-
return stmt.run(
|
|
183
|
+
return stmt.run(rowid, buffer);
|
|
219
184
|
}
|
|
220
185
|
/**
|
|
221
186
|
* Get last inserted row ID
|
|
@@ -298,33 +263,61 @@ class SQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
298
263
|
throw new Error(`Migration ${file} failed: ${message}`);
|
|
299
264
|
}
|
|
300
265
|
}
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
266
|
+
// Ensure embeddings table exists (plain table, no native extensions)
|
|
267
|
+
const embeddingsTables = this.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='embeddings'`).all();
|
|
268
|
+
if (embeddingsTables.length === 0) {
|
|
269
|
+
(0, debug_logger_js_1.info)('[sqlite-adapter] Creating embeddings table');
|
|
270
|
+
this.exec(`
|
|
271
|
+
CREATE TABLE embeddings (
|
|
272
|
+
rowid INTEGER PRIMARY KEY,
|
|
273
|
+
embedding BLOB NOT NULL
|
|
274
|
+
)
|
|
275
|
+
`);
|
|
276
|
+
}
|
|
277
|
+
// Always attempt migration — uses INSERT OR IGNORE so safe to run multiple times
|
|
278
|
+
this._migrateFromVssMemories();
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Attempt to migrate data from legacy vss_memories (sqlite-vec) to embeddings table.
|
|
282
|
+
* This is best-effort: if sqlite-vec is not loaded, the vss_memories table won't be readable.
|
|
283
|
+
*/
|
|
284
|
+
_migrateFromVssMemories() {
|
|
285
|
+
try {
|
|
286
|
+
const vssTables = this.prepare(`SELECT name FROM sqlite_master WHERE name='vss_memories'`).all();
|
|
307
287
|
if (vssTables.length === 0) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
embedding
|
|
312
|
-
|
|
313
|
-
|
|
288
|
+
return; // No legacy table
|
|
289
|
+
}
|
|
290
|
+
// Try to read from vss_memories — will fail if sqlite-vec extension isn't loaded
|
|
291
|
+
const rows = this.prepare('SELECT rowid, embedding FROM vss_memories').all();
|
|
292
|
+
if (rows.length > 0) {
|
|
293
|
+
const insertStmt = this.prepare('INSERT OR IGNORE INTO embeddings (rowid, embedding) VALUES (?, ?)');
|
|
294
|
+
let migrated = 0;
|
|
295
|
+
for (const row of rows) {
|
|
296
|
+
const res = insertStmt.run(row.rowid, row.embedding);
|
|
297
|
+
if (res.changes > 0)
|
|
298
|
+
migrated++;
|
|
299
|
+
}
|
|
300
|
+
(0, debug_logger_js_1.info)(`[sqlite-adapter] Migrated ${migrated} embeddings from vss_memories to embeddings`);
|
|
314
301
|
}
|
|
315
302
|
}
|
|
316
|
-
|
|
317
|
-
|
|
303
|
+
catch (err) {
|
|
304
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
305
|
+
(0, debug_logger_js_1.warn)(`[sqlite-adapter] Could not migrate from vss_memories (expected if sqlite-vec not installed): ${message}`);
|
|
318
306
|
}
|
|
319
307
|
}
|
|
320
308
|
}
|
|
321
309
|
exports.SQLiteAdapter = SQLiteAdapter;
|
|
322
310
|
exports.default = SQLiteAdapter;
|
|
323
311
|
function bufferToVector(buffer) {
|
|
324
|
-
if (!buffer) {
|
|
312
|
+
if (!buffer || buffer.byteLength % 4 !== 0) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
317
|
+
return new Float32Array(arrayBuffer);
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
325
320
|
return null;
|
|
326
321
|
}
|
|
327
|
-
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
328
|
-
return new Float32Array(arrayBuffer);
|
|
329
322
|
}
|
|
330
323
|
//# sourceMappingURL=sqlite-adapter.js.map
|
package/dist/db-manager.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MAMA Database Manager (SQLite-only)
|
|
3
3
|
*
|
|
4
4
|
* SQLite-exclusive database interface for MAMA Plugin.
|
|
5
|
-
* Uses better-sqlite3
|
|
5
|
+
* Uses better-sqlite3 for local storage.
|
|
6
6
|
*
|
|
7
7
|
* PostgreSQL support is only available in the legacy mcp-server repository.
|
|
8
8
|
*
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - WAL mode for better concurrency
|
|
11
11
|
* - synchronous=NORMAL for performance
|
|
12
12
|
* - Automatic migration management
|
|
13
|
-
* - Vector similarity search (
|
|
13
|
+
* - Vector similarity search (pure TS cosine similarity)
|
|
14
14
|
*
|
|
15
15
|
* @module db-manager
|
|
16
16
|
* @version 2.1 (Plugin - SQLite-only)
|
|
@@ -143,8 +143,7 @@ export declare function closeDB(): Promise<void>;
|
|
|
143
143
|
/**
|
|
144
144
|
* Insert embedding into vector search table
|
|
145
145
|
*
|
|
146
|
-
*
|
|
147
|
-
* Gracefully degrades if sqlite-vec is not available
|
|
146
|
+
* Stores embedding in the embeddings table for vector similarity search
|
|
148
147
|
*
|
|
149
148
|
* @param decisionRowid - SQLite rowid
|
|
150
149
|
* @param embedding - 384-dim embedding vector
|
package/dist/db-manager.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* MAMA Database Manager (SQLite-only)
|
|
4
4
|
*
|
|
5
5
|
* SQLite-exclusive database interface for MAMA Plugin.
|
|
6
|
-
* Uses better-sqlite3
|
|
6
|
+
* Uses better-sqlite3 for local storage.
|
|
7
7
|
*
|
|
8
8
|
* PostgreSQL support is only available in the legacy mcp-server repository.
|
|
9
9
|
*
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - WAL mode for better concurrency
|
|
12
12
|
* - synchronous=NORMAL for performance
|
|
13
13
|
* - Automatic migration management
|
|
14
|
-
* - Vector similarity search (
|
|
14
|
+
* - Vector similarity search (pure TS cosine similarity)
|
|
15
15
|
*
|
|
16
16
|
* @module db-manager
|
|
17
17
|
* @version 2.1 (Plugin - SQLite-only)
|
|
@@ -142,8 +142,7 @@ async function closeDB() {
|
|
|
142
142
|
/**
|
|
143
143
|
* Insert embedding into vector search table
|
|
144
144
|
*
|
|
145
|
-
*
|
|
146
|
-
* Gracefully degrades if sqlite-vec is not available
|
|
145
|
+
* Stores embedding in the embeddings table for vector similarity search
|
|
147
146
|
*
|
|
148
147
|
* @param decisionRowid - SQLite rowid
|
|
149
148
|
* @param embedding - 384-dim embedding vector
|
|
@@ -172,7 +171,7 @@ async function insertEmbedding(decisionRowid, embedding) {
|
|
|
172
171
|
async function vectorSearch(queryEmbedding, limit = 5, threshold = 0.7) {
|
|
173
172
|
const adapter = getAdapter();
|
|
174
173
|
try {
|
|
175
|
-
//
|
|
174
|
+
// Brute-force cosine similarity over all embeddings
|
|
176
175
|
const results = await adapter.vectorSearch(queryEmbedding, limit * 3);
|
|
177
176
|
if (!results || results.length === 0) {
|
|
178
177
|
return []; // No keyword fallback - fast fail
|
|
@@ -185,7 +185,7 @@ export declare function getSupersededChainDepth(topic: string): Promise<{
|
|
|
185
185
|
* Task 3.5: If previous exists: Create supersedes edge, Update previous superseded_by
|
|
186
186
|
* Task 3.6: If multi-parent refinement: Store refined_from, Calculate combined confidence
|
|
187
187
|
* Task 3.7: Generate enhanced embedding
|
|
188
|
-
* Task 3.8: Store
|
|
188
|
+
* Task 3.8: Store embedding (link via rowid)
|
|
189
189
|
*
|
|
190
190
|
* AC #1: Decision stored with outcome=NULL, confidence from LLM
|
|
191
191
|
* AC #2: Supersedes relationship creation
|
package/dist/decision-tracker.js
CHANGED
|
@@ -380,7 +380,7 @@ async function getSupersededChainDepth(topic) {
|
|
|
380
380
|
* Task 3.5: If previous exists: Create supersedes edge, Update previous superseded_by
|
|
381
381
|
* Task 3.6: If multi-parent refinement: Store refined_from, Calculate combined confidence
|
|
382
382
|
* Task 3.7: Generate enhanced embedding
|
|
383
|
-
* Task 3.8: Store
|
|
383
|
+
* Task 3.8: Store embedding (link via rowid)
|
|
384
384
|
*
|
|
385
385
|
* AC #1: Decision stored with outcome=NULL, confidence from LLM
|
|
386
386
|
* AC #2: Supersedes relationship creation
|
|
@@ -461,7 +461,7 @@ async function learnDecision(detection, toolExecution, sessionContext) {
|
|
|
461
461
|
: null,
|
|
462
462
|
risks: detection.risks || null,
|
|
463
463
|
};
|
|
464
|
-
// Task 3.7, 3.8: Generate enhanced embedding and store in
|
|
464
|
+
// Task 3.7, 3.8: Generate enhanced embedding and store in embeddings table
|
|
465
465
|
// (Handled by insertDecisionWithEmbedding function)
|
|
466
466
|
await (0, memory_store_js_1.insertDecisionWithEmbedding)(decision);
|
|
467
467
|
// ════════════════════════════════════════════════════════
|
package/dist/embeddings.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @date 2025-11-20
|
|
11
11
|
*/
|
|
12
12
|
import { embeddingCache } from './embedding-cache.js';
|
|
13
|
-
import { loadConfig, getModelName, getEmbeddingDim } from './config-loader.js';
|
|
13
|
+
import { loadConfig, getModelName, getEmbeddingDim, getQuantized } from './config-loader.js';
|
|
14
14
|
/**
|
|
15
15
|
* Decision object for enhanced embedding generation
|
|
16
16
|
*/
|
|
@@ -71,5 +71,5 @@ export declare function cosineSimilarity(embA: Float32Array, embB: Float32Array)
|
|
|
71
71
|
export { embeddingCache };
|
|
72
72
|
export declare const EMBEDDING_DIM: number;
|
|
73
73
|
export declare const MODEL_NAME: string;
|
|
74
|
-
export { loadConfig, getModelName, getEmbeddingDim };
|
|
74
|
+
export { loadConfig, getModelName, getEmbeddingDim, getQuantized };
|
|
75
75
|
//# sourceMappingURL=embeddings.d.ts.map
|
package/dist/embeddings.js
CHANGED
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.getEmbeddingDim = exports.getModelName = exports.loadConfig = exports.MODEL_NAME = exports.EMBEDDING_DIM = exports.embeddingCache = void 0;
|
|
17
|
+
exports.getQuantized = exports.getEmbeddingDim = exports.getModelName = exports.loadConfig = exports.MODEL_NAME = exports.EMBEDDING_DIM = exports.embeddingCache = void 0;
|
|
18
18
|
exports.generateEmbedding = generateEmbedding;
|
|
19
19
|
exports.generateEnhancedEmbedding = generateEnhancedEmbedding;
|
|
20
20
|
exports.generateBatchEmbeddings = generateBatchEmbeddings;
|
|
@@ -29,6 +29,7 @@ const config_loader_js_1 = require("./config-loader.js");
|
|
|
29
29
|
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_loader_js_1.loadConfig; } });
|
|
30
30
|
Object.defineProperty(exports, "getModelName", { enumerable: true, get: function () { return config_loader_js_1.getModelName; } });
|
|
31
31
|
Object.defineProperty(exports, "getEmbeddingDim", { enumerable: true, get: function () { return config_loader_js_1.getEmbeddingDim; } });
|
|
32
|
+
Object.defineProperty(exports, "getQuantized", { enumerable: true, get: function () { return config_loader_js_1.getQuantized; } });
|
|
32
33
|
// Shared cache directory (not in node_modules)
|
|
33
34
|
const DEFAULT_CACHE_DIR = path_1.default.join(os_1.default.homedir(), '.cache', 'huggingface', 'transformers');
|
|
34
35
|
// Singleton pattern for model loading
|
|
@@ -73,11 +74,14 @@ async function loadModel() {
|
|
|
73
74
|
const cacheDir = process.env.HF_HOME || process.env.TRANSFORMERS_CACHE || DEFAULT_CACHE_DIR;
|
|
74
75
|
env.cacheDir = cacheDir;
|
|
75
76
|
(0, debug_logger_js_1.info)(`[MAMA] Model cache directory: ${cacheDir}`);
|
|
76
|
-
|
|
77
|
+
const quantized = (0, config_loader_js_1.getQuantized)();
|
|
78
|
+
embeddingPipeline = (await pipeline('feature-extraction', modelName, {
|
|
79
|
+
dtype: quantized ? 'q8' : 'fp32',
|
|
80
|
+
}));
|
|
77
81
|
currentModelName = modelName;
|
|
78
82
|
const loadTime = Date.now() - startTime;
|
|
79
83
|
const config = (0, config_loader_js_1.loadConfig)();
|
|
80
|
-
(0, progress_indicator_js_1.logComplete)(`Embedding model ready (${loadTime}ms, ${config.embeddingDim}-dim)`);
|
|
84
|
+
(0, progress_indicator_js_1.logComplete)(`Embedding model ready (${loadTime}ms, ${config.embeddingDim}-dim, ${quantized ? 'q8' : 'fp32'})`);
|
|
81
85
|
}
|
|
82
86
|
catch (loadErr) {
|
|
83
87
|
modelLoadFailed = true;
|
package/dist/mama-api.js
CHANGED
|
@@ -681,7 +681,7 @@ async function suggest(userQuestion, options = {}) {
|
|
|
681
681
|
let results = [];
|
|
682
682
|
let searchMethod = 'vector';
|
|
683
683
|
try {
|
|
684
|
-
// Check if vector search is available
|
|
684
|
+
// Check if vector search is available
|
|
685
685
|
if (!(0, memory_store_js_1.getAdapter)().vectorSearchEnabled) {
|
|
686
686
|
throw new Error('Vector search not available');
|
|
687
687
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungjaehoon/mama-core",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "MAMA Core - Shared modules for Memory-Augmented MCP Assistant",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -62,11 +62,8 @@
|
|
|
62
62
|
"node": ">=18.0.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@anthropic-ai/sdk": "^0.72.1",
|
|
66
65
|
"@huggingface/transformers": "^3.8.1",
|
|
67
66
|
"better-sqlite3": "^11.0.0",
|
|
68
|
-
"mime-types": "^3.0.2",
|
|
69
|
-
"sqlite-vec": "^0.1.0",
|
|
70
67
|
"ws": "^8.19.0"
|
|
71
68
|
},
|
|
72
69
|
"devDependencies": {
|