@plures/superlocalmemory-mcp 0.2.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 +661 -0
- package/README.md +228 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -0
- package/dist/db/memory.d.ts +95 -0
- package/dist/db/memory.d.ts.map +1 -0
- package/dist/db/memory.js +245 -0
- package/dist/db/memory.js.map +1 -0
- package/dist/embeddings/index.d.ts +16 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +26 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/openai.d.ts +17 -0
- package/dist/embeddings/openai.d.ts.map +1 -0
- package/dist/embeddings/openai.js +62 -0
- package/dist/embeddings/openai.js.map +1 -0
- package/dist/embeddings/transformers.d.ts +18 -0
- package/dist/embeddings/transformers.d.ts.map +1 -0
- package/dist/embeddings/transformers.js +59 -0
- package/dist/embeddings/transformers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +378 -0
- package/dist/server.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# @plures/superlocalmemory-mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for **superlocalmemory** — a **local-first, persistent vector memory** for AI coding assistants.
|
|
4
|
+
|
|
5
|
+
It exposes a small set of MCP **tools** and **resources** so editors like VS Code (Copilot MCP), Cursor, Continue, and Claude Desktop can store and recall long-term memory during coding sessions.
|
|
6
|
+
|
|
7
|
+
- Storage: local SQLite file (better-sqlite3)
|
|
8
|
+
- Retrieval: semantic vector search
|
|
9
|
+
- Embeddings: **Transformers.js (default, zero-config)** or OpenAI (optional)
|
|
10
|
+
|
|
11
|
+
## ✨ Zero-Config Usage
|
|
12
|
+
|
|
13
|
+
**No API keys required!** Just run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @plures/superlocalmemory-mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The server uses **Transformers.js** to run embeddings locally in-process with the `bge-small-en-v1.5` model (384 dimensions).
|
|
20
|
+
|
|
21
|
+
> **Note:** First run will download the model (~100MB) to `~/.cache/superlocalmemory/transformers`. Subsequent runs are instant and fully offline.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Run directly (recommended):
|
|
27
|
+
npx @plures/superlocalmemory-mcp
|
|
28
|
+
|
|
29
|
+
# Or install globally:
|
|
30
|
+
npm install -g @plures/superlocalmemory-mcp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
All configuration is **optional**:
|
|
36
|
+
|
|
37
|
+
### Environment Variables
|
|
38
|
+
|
|
39
|
+
- `SUPERLOCALMEMORY_DB_PATH` (optional) — SQLite DB path (default: `~/.superlocalmemory/mcp.db`)
|
|
40
|
+
- `SUPERLOCALMEMORY_DEBUG` (optional) — set to `true` for debug logs to stderr
|
|
41
|
+
- `SUPERLOCALMEMORY_CACHE_DIR` (optional) — Transformers.js model cache directory (default: `~/.cache/superlocalmemory/transformers`)
|
|
42
|
+
- `OPENAI_API_KEY` (optional) — use OpenAI embeddings instead of local Transformers.js
|
|
43
|
+
- `OPENAI_EMBEDDING_MODEL` (optional) — OpenAI model to use (default: `text-embedding-3-small`)
|
|
44
|
+
|
|
45
|
+
### Using OpenAI (Optional)
|
|
46
|
+
|
|
47
|
+
If you prefer OpenAI embeddings over local Transformers.js:
|
|
48
|
+
|
|
49
|
+
1. Set `OPENAI_API_KEY` in your environment
|
|
50
|
+
2. The server will use OpenAI with 1536-dim embeddings
|
|
51
|
+
|
|
52
|
+
## Migration / Breaking Changes
|
|
53
|
+
|
|
54
|
+
> **Important:** Embedding dimensions are **not** interchangeable. Transformers.js uses **384‑dim** embeddings, while OpenAI uses **1536‑dim** embeddings by default.
|
|
55
|
+
|
|
56
|
+
If you already have an existing database:
|
|
57
|
+
|
|
58
|
+
- **Databases created with OpenAI embeddings must continue using `OPENAI_API_KEY`.**
|
|
59
|
+
- Do **not** switch that database to Transformers.js; the stored vectors will be incompatible.
|
|
60
|
+
- The server will detect dimension mismatches and provide a clear error message.
|
|
61
|
+
- There is **no automatic migration** between 384‑dim and 1536‑dim embeddings.
|
|
62
|
+
- To change providers (OpenAI ⇄ Transformers.js), you must either:
|
|
63
|
+
- Point `SUPERLOCALMEMORY_DB_PATH` to a **new database**, or
|
|
64
|
+
- Delete/recreate the existing DB and **re-index all memories**.
|
|
65
|
+
## Editor setup
|
|
66
|
+
|
|
67
|
+
### Zero-Config Examples
|
|
68
|
+
|
|
69
|
+
These examples require **no environment variables** and work out of the box:
|
|
70
|
+
|
|
71
|
+
#### VS Code (Copilot) — `mcp.json`
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"superlocalmemory": {
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["@plures/superlocalmemory-mcp"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Cursor — `settings.json`
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"superlocalmemory": {
|
|
90
|
+
"command": "npx",
|
|
91
|
+
"args": ["@plures/superlocalmemory-mcp"]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Continue.dev — `config.json`
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": [
|
|
102
|
+
{
|
|
103
|
+
"name": "superlocalmemory",
|
|
104
|
+
"command": "npx",
|
|
105
|
+
"args": ["@plures/superlocalmemory-mcp"]
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Claude Desktop — `claude_desktop_config.json`
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"superlocalmemory": {
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": ["@plures/superlocalmemory-mcp"]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### With OpenAI (Optional)
|
|
125
|
+
|
|
126
|
+
If you prefer OpenAI embeddings:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"superlocalmemory": {
|
|
132
|
+
"command": "npx",
|
|
133
|
+
"args": ["@plures/superlocalmemory-mcp"],
|
|
134
|
+
"env": {
|
|
135
|
+
"OPENAI_API_KEY": "your-key"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Tools
|
|
143
|
+
|
|
144
|
+
### `memory_store`
|
|
145
|
+
Store a memory.
|
|
146
|
+
|
|
147
|
+
**Input**
|
|
148
|
+
- `content` (string, required)
|
|
149
|
+
- `tags` (string[], optional)
|
|
150
|
+
- `category` (string, optional)
|
|
151
|
+
- `source` (string, optional)
|
|
152
|
+
|
|
153
|
+
### `memory_search`
|
|
154
|
+
Semantic search.
|
|
155
|
+
|
|
156
|
+
**Input**
|
|
157
|
+
- `query` (string, required)
|
|
158
|
+
- `limit` (number, optional, default 5)
|
|
159
|
+
- `minScore` (number, optional, default 0.3)
|
|
160
|
+
|
|
161
|
+
### `memory_forget`
|
|
162
|
+
Delete by UUID `id` or by semantic `query`.
|
|
163
|
+
|
|
164
|
+
**Input**
|
|
165
|
+
- `id` (string, optional)
|
|
166
|
+
- `query` (string, optional)
|
|
167
|
+
- `threshold` (number, optional, default 0.8)
|
|
168
|
+
|
|
169
|
+
### `memory_profile`
|
|
170
|
+
Return the stored user profile summary (if any).
|
|
171
|
+
|
|
172
|
+
### `memory_index`
|
|
173
|
+
Index a directory by storing file contents as memories.
|
|
174
|
+
|
|
175
|
+
**Input**
|
|
176
|
+
- `directory` (string, required)
|
|
177
|
+
- `maxFiles` (number, optional, default 500)
|
|
178
|
+
- `maxBytesPerFile` (number, optional, default 200000)
|
|
179
|
+
- `category` (string, optional, default `project-context`)
|
|
180
|
+
- `tags` (string[], optional)
|
|
181
|
+
|
|
182
|
+
### `memory_stats`
|
|
183
|
+
Return database stats.
|
|
184
|
+
|
|
185
|
+
## Resources
|
|
186
|
+
|
|
187
|
+
- `memory://profile` — JSON user profile (if available)
|
|
188
|
+
- `memory://recent` — markdown list of the 20 most recent memory contents
|
|
189
|
+
- `memory://stats` — JSON stats
|
|
190
|
+
|
|
191
|
+
## How it works
|
|
192
|
+
|
|
193
|
+
This server provides local-first persistent memory with:
|
|
194
|
+
|
|
195
|
+
- **Local SQLite database** stores memory rows with embeddings
|
|
196
|
+
- **Embeddings**:
|
|
197
|
+
- Default: Transformers.js (`bge-small-en-v1.5`, 384-dim) — runs in-process, zero-config
|
|
198
|
+
- Optional: OpenAI API (`text-embedding-3-small`, 1536-dim) — requires API key
|
|
199
|
+
- **Vector search**: In-process cosine similarity against stored embeddings
|
|
200
|
+
- **Indexing**: `memory_index` walks a directory, reads text files, and stores them for later retrieval
|
|
201
|
+
|
|
202
|
+
## Privacy
|
|
203
|
+
|
|
204
|
+
All memory data is stored **locally** on your machine at `SUPERLOCALMEMORY_DB_PATH` (default: `~/.superlocalmemory/mcp.db`).
|
|
205
|
+
|
|
206
|
+
### Network Usage
|
|
207
|
+
|
|
208
|
+
- **Transformers.js (default)**: One-time model download (~100MB) on first run, then 100% offline
|
|
209
|
+
- **OpenAI (optional)**: API calls for each embedding when `OPENAI_API_KEY` is set
|
|
210
|
+
|
|
211
|
+
No memory content is ever sent to external services except for embedding generation when using OpenAI.
|
|
212
|
+
|
|
213
|
+
## Development
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
npm install
|
|
217
|
+
npm run dev
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Build:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npm run build
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
AGPL-3.0
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AASD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,CAO1E"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function expandHome(p) {
|
|
4
|
+
if (!p)
|
|
5
|
+
return p;
|
|
6
|
+
if (p === "~")
|
|
7
|
+
return os.homedir();
|
|
8
|
+
if (p.startsWith("~/"))
|
|
9
|
+
return path.join(os.homedir(), p.slice(2));
|
|
10
|
+
return p;
|
|
11
|
+
}
|
|
12
|
+
export function loadConfig(env = process.env) {
|
|
13
|
+
const dbPath = expandHome(env.SUPERLOCALMEMORY_DB_PATH ?? "~/.superlocalmemory/mcp.db");
|
|
14
|
+
const openaiApiKey = env.OPENAI_API_KEY;
|
|
15
|
+
const openaiModel = env.OPENAI_EMBEDDING_MODEL;
|
|
16
|
+
const debug = (env.SUPERLOCALMEMORY_DEBUG ?? "").toLowerCase() === "true";
|
|
17
|
+
return { dbPath, openaiApiKey, openaiModel, debug };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjB,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,wBAAwB,IAAI,4BAA4B,CAAC,CAAC;IACxF,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,CAAC;IACxC,MAAM,WAAW,GAAG,GAAG,CAAC,sBAAsB,CAAC;IAC/C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAE1E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export interface MemoryEntry {
|
|
2
|
+
id: string;
|
|
3
|
+
content: string;
|
|
4
|
+
embedding: string;
|
|
5
|
+
tags: string[];
|
|
6
|
+
category?: string;
|
|
7
|
+
source: string;
|
|
8
|
+
created_at: number;
|
|
9
|
+
}
|
|
10
|
+
export interface StoreOptions {
|
|
11
|
+
tags?: string[];
|
|
12
|
+
category?: string;
|
|
13
|
+
source?: string;
|
|
14
|
+
dedupeThreshold?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface StoreResult {
|
|
17
|
+
entry: MemoryEntry;
|
|
18
|
+
isDuplicate: boolean;
|
|
19
|
+
updatedId?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SearchResult {
|
|
22
|
+
entry: MemoryEntry;
|
|
23
|
+
score: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Local SQLite-based vector memory database.
|
|
27
|
+
* Supports storage, cosine similarity search, and CRUD operations.
|
|
28
|
+
*/
|
|
29
|
+
export declare class MemoryDB {
|
|
30
|
+
private db;
|
|
31
|
+
private dimension;
|
|
32
|
+
constructor(dbPath: string, dimension: number);
|
|
33
|
+
private initTables;
|
|
34
|
+
/**
|
|
35
|
+
* Validate that existing embeddings in the database match the configured dimension.
|
|
36
|
+
* This prevents dimension mismatches when switching between embedding providers.
|
|
37
|
+
*/
|
|
38
|
+
private validateDimension;
|
|
39
|
+
/**
|
|
40
|
+
* Calculate cosine similarity between two vectors
|
|
41
|
+
*/
|
|
42
|
+
private cosineSimilarity;
|
|
43
|
+
/**
|
|
44
|
+
* Store a memory with deduplication
|
|
45
|
+
*/
|
|
46
|
+
store(content: string, embedding: number[], options?: StoreOptions): Promise<StoreResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Find a similar memory above threshold (for deduplication)
|
|
49
|
+
*/
|
|
50
|
+
private findSimilar;
|
|
51
|
+
/**
|
|
52
|
+
* Vector search using cosine similarity.
|
|
53
|
+
*
|
|
54
|
+
* Performance note: This implementation loads all embeddings into memory and performs
|
|
55
|
+
* brute-force cosine similarity computation. For large databases (>10,000 memories),
|
|
56
|
+
* this may have performance implications. Future optimizations could include:
|
|
57
|
+
* - Approximate nearest neighbor search (ANN)
|
|
58
|
+
* - Vector indexing (e.g., HNSW, IVF)
|
|
59
|
+
* - Limiting search scope with filters
|
|
60
|
+
*/
|
|
61
|
+
vectorSearch(queryEmbedding: number[], limit?: number, minScore?: number): Promise<SearchResult[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Delete a memory by ID
|
|
64
|
+
*/
|
|
65
|
+
delete(id: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Delete memories matching a query above threshold
|
|
68
|
+
*/
|
|
69
|
+
deleteByQuery(queryEmbedding: number[], threshold?: number): Promise<number>;
|
|
70
|
+
/**
|
|
71
|
+
* Get user profile (stub - not implemented in core)
|
|
72
|
+
*/
|
|
73
|
+
getProfile(): string | null;
|
|
74
|
+
/**
|
|
75
|
+
* Get all memory content (limited)
|
|
76
|
+
*/
|
|
77
|
+
getAllContent(limit?: number): string[];
|
|
78
|
+
/**
|
|
79
|
+
* Get database statistics
|
|
80
|
+
*/
|
|
81
|
+
stats(): {
|
|
82
|
+
totalMemories: number;
|
|
83
|
+
captureCount: number;
|
|
84
|
+
dimension: number;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Increment capture count
|
|
88
|
+
*/
|
|
89
|
+
incrementCaptureCount(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Close database connection
|
|
92
|
+
*/
|
|
93
|
+
close(): void;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/db/memory.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQ7C,OAAO,CAAC,UAAU;IAiClB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;OAEG;IACG,KAAK,CACT,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC;IAwEvB;;OAEG;YACW,WAAW;IAQzB;;;;;;;;;OASG;IACG,YAAY,CAChB,cAAc,EAAE,MAAM,EAAE,EACxB,KAAK,SAAI,EACT,QAAQ,SAAM,GACb,OAAO,CAAC,YAAY,EAAE,CAAC;IAkD1B;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIxB;;OAEG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EAAE,EACxB,SAAS,SAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAYlB;;OAEG;IACH,UAAU,IAAI,MAAM,GAAG,IAAI;IAM3B;;OAEG;IACH,aAAa,CAAC,KAAK,SAAK,GAAG,MAAM,EAAE;IAQnC;;OAEG;IACH,KAAK,IAAI;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB;IAkBD;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAO7B;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
/**
|
|
4
|
+
* Local SQLite-based vector memory database.
|
|
5
|
+
* Supports storage, cosine similarity search, and CRUD operations.
|
|
6
|
+
*/
|
|
7
|
+
export class MemoryDB {
|
|
8
|
+
db;
|
|
9
|
+
dimension;
|
|
10
|
+
constructor(dbPath, dimension) {
|
|
11
|
+
this.dimension = dimension;
|
|
12
|
+
this.db = new Database(dbPath);
|
|
13
|
+
this.db.pragma("journal_mode = WAL");
|
|
14
|
+
this.initTables();
|
|
15
|
+
this.validateDimension();
|
|
16
|
+
}
|
|
17
|
+
initTables() {
|
|
18
|
+
// Create memories table
|
|
19
|
+
this.db.exec(`
|
|
20
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
content TEXT NOT NULL,
|
|
23
|
+
embedding TEXT NOT NULL,
|
|
24
|
+
tags TEXT,
|
|
25
|
+
category TEXT,
|
|
26
|
+
source TEXT,
|
|
27
|
+
created_at INTEGER NOT NULL
|
|
28
|
+
)
|
|
29
|
+
`);
|
|
30
|
+
// Create metadata table for stats
|
|
31
|
+
this.db.exec(`
|
|
32
|
+
CREATE TABLE IF NOT EXISTS metadata (
|
|
33
|
+
key TEXT PRIMARY KEY,
|
|
34
|
+
value TEXT NOT NULL
|
|
35
|
+
)
|
|
36
|
+
`);
|
|
37
|
+
// Initialize capture count if not exists
|
|
38
|
+
const stmt = this.db.prepare("SELECT value FROM metadata WHERE key = ?");
|
|
39
|
+
const row = stmt.get("capture_count");
|
|
40
|
+
if (!row) {
|
|
41
|
+
this.db.prepare("INSERT INTO metadata (key, value) VALUES (?, ?)").run("capture_count", "0");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate that existing embeddings in the database match the configured dimension.
|
|
46
|
+
* This prevents dimension mismatches when switching between embedding providers.
|
|
47
|
+
*/
|
|
48
|
+
validateDimension() {
|
|
49
|
+
const stmt = this.db.prepare("SELECT embedding FROM memories LIMIT 1");
|
|
50
|
+
const row = stmt.get();
|
|
51
|
+
if (row) {
|
|
52
|
+
try {
|
|
53
|
+
const existingEmbedding = JSON.parse(row.embedding);
|
|
54
|
+
if (existingEmbedding.length !== this.dimension) {
|
|
55
|
+
throw new Error(`Database dimension mismatch: Database contains ${existingEmbedding.length}-dim embeddings, ` +
|
|
56
|
+
`but configured provider uses ${this.dimension}-dim embeddings. ` +
|
|
57
|
+
`To fix this, either:\n` +
|
|
58
|
+
` 1. Set OPENAI_API_KEY to use OpenAI (1536-dim) if database was created with OpenAI\n` +
|
|
59
|
+
` 2. Use a new database path with SUPERLOCALMEMORY_DB_PATH\n` +
|
|
60
|
+
` 3. Delete the existing database to start fresh with ${this.dimension}-dim embeddings`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (err instanceof Error && err.message.includes("Database dimension mismatch")) {
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
// Ignore JSON parse errors for corrupted data - will be handled during search
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Calculate cosine similarity between two vectors
|
|
73
|
+
*/
|
|
74
|
+
cosineSimilarity(a, b) {
|
|
75
|
+
if (a.length !== b.length) {
|
|
76
|
+
throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);
|
|
77
|
+
}
|
|
78
|
+
let dotProduct = 0;
|
|
79
|
+
let normA = 0;
|
|
80
|
+
let normB = 0;
|
|
81
|
+
for (let i = 0; i < a.length; i++) {
|
|
82
|
+
dotProduct += a[i] * b[i];
|
|
83
|
+
normA += a[i] * a[i];
|
|
84
|
+
normB += b[i] * b[i];
|
|
85
|
+
}
|
|
86
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
87
|
+
return denom === 0 ? 0 : dotProduct / denom;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Store a memory with deduplication
|
|
91
|
+
*/
|
|
92
|
+
async store(content, embedding, options = {}) {
|
|
93
|
+
const { tags = [], category, source = "", dedupeThreshold = 0.95, } = options;
|
|
94
|
+
// Check for duplicates
|
|
95
|
+
const existing = await this.findSimilar(embedding, dedupeThreshold);
|
|
96
|
+
if (existing) {
|
|
97
|
+
// Update existing entry
|
|
98
|
+
const stmt = this.db.prepare("UPDATE memories SET content = ?, embedding = ?, tags = ?, category = ?, source = ?, created_at = ? WHERE id = ?");
|
|
99
|
+
stmt.run(content, JSON.stringify(embedding), JSON.stringify(tags), category || null, source, Date.now(), existing.id);
|
|
100
|
+
return {
|
|
101
|
+
entry: {
|
|
102
|
+
...existing,
|
|
103
|
+
content,
|
|
104
|
+
embedding: JSON.stringify(embedding),
|
|
105
|
+
tags,
|
|
106
|
+
category,
|
|
107
|
+
source,
|
|
108
|
+
created_at: Date.now(),
|
|
109
|
+
},
|
|
110
|
+
isDuplicate: true,
|
|
111
|
+
updatedId: existing.id,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// Insert new entry
|
|
115
|
+
const id = randomUUID();
|
|
116
|
+
const created_at = Date.now();
|
|
117
|
+
const stmt = this.db.prepare("INSERT INTO memories (id, content, embedding, tags, category, source, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
118
|
+
stmt.run(id, content, JSON.stringify(embedding), JSON.stringify(tags), category || null, source, created_at);
|
|
119
|
+
return {
|
|
120
|
+
entry: {
|
|
121
|
+
id,
|
|
122
|
+
content,
|
|
123
|
+
embedding: JSON.stringify(embedding),
|
|
124
|
+
tags,
|
|
125
|
+
category,
|
|
126
|
+
source,
|
|
127
|
+
created_at,
|
|
128
|
+
},
|
|
129
|
+
isDuplicate: false,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find a similar memory above threshold (for deduplication)
|
|
134
|
+
*/
|
|
135
|
+
async findSimilar(embedding, threshold) {
|
|
136
|
+
const results = await this.vectorSearch(embedding, 1, threshold);
|
|
137
|
+
return results.length > 0 ? results[0].entry : null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Vector search using cosine similarity.
|
|
141
|
+
*
|
|
142
|
+
* Performance note: This implementation loads all embeddings into memory and performs
|
|
143
|
+
* brute-force cosine similarity computation. For large databases (>10,000 memories),
|
|
144
|
+
* this may have performance implications. Future optimizations could include:
|
|
145
|
+
* - Approximate nearest neighbor search (ANN)
|
|
146
|
+
* - Vector indexing (e.g., HNSW, IVF)
|
|
147
|
+
* - Limiting search scope with filters
|
|
148
|
+
*/
|
|
149
|
+
async vectorSearch(queryEmbedding, limit = 5, minScore = 0.3) {
|
|
150
|
+
const stmt = this.db.prepare("SELECT * FROM memories");
|
|
151
|
+
const rows = stmt.all();
|
|
152
|
+
const results = [];
|
|
153
|
+
for (const row of rows) {
|
|
154
|
+
let embedding;
|
|
155
|
+
try {
|
|
156
|
+
embedding = JSON.parse(row.embedding);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
console.warn(`Skipping memory entry with invalid embedding JSON (id=${row.id}):`, err);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const score = this.cosineSimilarity(queryEmbedding, embedding);
|
|
163
|
+
if (score >= minScore) {
|
|
164
|
+
results.push({
|
|
165
|
+
entry: {
|
|
166
|
+
id: row.id,
|
|
167
|
+
content: row.content,
|
|
168
|
+
embedding: row.embedding,
|
|
169
|
+
tags: JSON.parse(row.tags || "[]"),
|
|
170
|
+
category: row.category || undefined,
|
|
171
|
+
source: row.source,
|
|
172
|
+
created_at: row.created_at,
|
|
173
|
+
},
|
|
174
|
+
score,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Sort by score descending
|
|
179
|
+
results.sort((a, b) => b.score - a.score);
|
|
180
|
+
// Limit results
|
|
181
|
+
return results.slice(0, limit);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Delete a memory by ID
|
|
185
|
+
*/
|
|
186
|
+
delete(id) {
|
|
187
|
+
this.db.prepare("DELETE FROM memories WHERE id = ?").run(id);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Delete memories matching a query above threshold
|
|
191
|
+
*/
|
|
192
|
+
async deleteByQuery(queryEmbedding, threshold = 0.8) {
|
|
193
|
+
const matches = await this.vectorSearch(queryEmbedding, 100, threshold);
|
|
194
|
+
let deleted = 0;
|
|
195
|
+
for (const match of matches) {
|
|
196
|
+
this.delete(match.entry.id);
|
|
197
|
+
deleted++;
|
|
198
|
+
}
|
|
199
|
+
return deleted;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get user profile (stub - not implemented in core)
|
|
203
|
+
*/
|
|
204
|
+
getProfile() {
|
|
205
|
+
const stmt = this.db.prepare("SELECT value FROM metadata WHERE key = ?");
|
|
206
|
+
const row = stmt.get("profile");
|
|
207
|
+
return row ? row.value : null;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get all memory content (limited)
|
|
211
|
+
*/
|
|
212
|
+
getAllContent(limit = 20) {
|
|
213
|
+
const stmt = this.db.prepare("SELECT content FROM memories ORDER BY created_at DESC LIMIT ?");
|
|
214
|
+
const rows = stmt.all(limit);
|
|
215
|
+
return rows.map((r) => r.content);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Get database statistics
|
|
219
|
+
*/
|
|
220
|
+
stats() {
|
|
221
|
+
const countStmt = this.db.prepare("SELECT COUNT(*) as count FROM memories");
|
|
222
|
+
const countRow = countStmt.get();
|
|
223
|
+
const captureStmt = this.db.prepare("SELECT value FROM metadata WHERE key = ?");
|
|
224
|
+
const captureRow = captureStmt.get("capture_count");
|
|
225
|
+
return {
|
|
226
|
+
totalMemories: countRow.count,
|
|
227
|
+
captureCount: captureRow ? parseInt(captureRow.value, 10) : 0,
|
|
228
|
+
dimension: this.dimension,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Increment capture count
|
|
233
|
+
*/
|
|
234
|
+
incrementCaptureCount() {
|
|
235
|
+
const stmt = this.db.prepare("UPDATE metadata SET value = CAST((CAST(value AS INTEGER) + 1) AS TEXT) WHERE key = ?");
|
|
236
|
+
stmt.run("capture_count");
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Close database connection
|
|
240
|
+
*/
|
|
241
|
+
close() {
|
|
242
|
+
this.db.close();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/db/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TransformersEmbeddings } from "./transformers.js";
|
|
2
|
+
import { OpenAIEmbeddings } from "./openai.js";
|
|
3
|
+
import type { EmbeddingProvider } from "./transformers.js";
|
|
4
|
+
export type { EmbeddingProvider };
|
|
5
|
+
export { TransformersEmbeddings, OpenAIEmbeddings };
|
|
6
|
+
export interface EmbeddingConfig {
|
|
7
|
+
openaiApiKey?: string;
|
|
8
|
+
openaiModel?: string;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create an embedding provider based on available configuration.
|
|
13
|
+
* Defaults to Transformers.js (zero-config), with OpenAI as optional override.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createEmbeddings(config?: EmbeddingConfig): Promise<EmbeddingProvider>;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/embeddings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAmB5B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TransformersEmbeddings } from "./transformers.js";
|
|
2
|
+
import { OpenAIEmbeddings } from "./openai.js";
|
|
3
|
+
export { TransformersEmbeddings, OpenAIEmbeddings };
|
|
4
|
+
/**
|
|
5
|
+
* Create an embedding provider based on available configuration.
|
|
6
|
+
* Defaults to Transformers.js (zero-config), with OpenAI as optional override.
|
|
7
|
+
*/
|
|
8
|
+
export async function createEmbeddings(config = {}) {
|
|
9
|
+
const { openaiApiKey, openaiModel, debug = false } = config;
|
|
10
|
+
// If OpenAI key is provided, use OpenAI (fail fast on error)
|
|
11
|
+
if (openaiApiKey) {
|
|
12
|
+
if (debug) {
|
|
13
|
+
console.error("[Embeddings] Using OpenAI provider");
|
|
14
|
+
}
|
|
15
|
+
// When an explicit OpenAI API key is provided, fail fast instead of silently
|
|
16
|
+
// falling back to a different provider with incompatible dimensions.
|
|
17
|
+
// This prevents dimension mismatch errors with existing databases.
|
|
18
|
+
return new OpenAIEmbeddings(openaiApiKey, openaiModel, debug);
|
|
19
|
+
}
|
|
20
|
+
// Default: Transformers.js (zero-config)
|
|
21
|
+
if (debug) {
|
|
22
|
+
console.error("[Embeddings] Using Transformers.js provider (zero-config)");
|
|
23
|
+
}
|
|
24
|
+
return new TransformersEmbeddings(debug);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/embeddings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAI/C,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;AAQpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAA0B,EAAE;IAE5B,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC;IAE5D,6DAA6D;IAC7D,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACtD,CAAC;QACD,6EAA6E;QAC7E,qEAAqE;QACrE,mEAAmE;QACnE,OAAO,IAAI,gBAAgB,CAAC,YAAY,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;IAED,yCAAyC;IACzC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC"}
|