@memvid/sdk 2.0.140 → 2.0.142
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 +222 -277
- package/dist/index.js +27 -6
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @memvid/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A single-file AI memory system for Node.js. Store documents, search with BM25 + vector ranking, and run RAG queries from a portable `.mv2` file.
|
|
4
4
|
|
|
5
|
-
Built on Rust via N-API
|
|
5
|
+
Built on Rust via N-API. No database setup, no external services required.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -10,392 +10,337 @@ Built on Rust via N-API for native performance. No database setup, no network de
|
|
|
10
10
|
npm install @memvid/sdk
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The package automatically installs the correct binary for your platform (macOS, Linux, or Windows).
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
import { use, create } from "@memvid/sdk";
|
|
15
|
+
## Quick Start
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
```javascript
|
|
18
|
+
import { create } from "@memvid/sdk";
|
|
19
|
+
|
|
20
|
+
// Create a memory file
|
|
21
|
+
const mv = await create("notes.mv2");
|
|
20
22
|
|
|
21
|
-
// Store
|
|
23
|
+
// Store some documents
|
|
22
24
|
await mv.put({
|
|
23
|
-
title: "Project
|
|
25
|
+
title: "Project Update",
|
|
24
26
|
label: "meeting",
|
|
25
|
-
text: "Discussed
|
|
26
|
-
metadata: { date: "2024-01-15" }
|
|
27
|
+
text: "Discussed Q4 roadmap. Alice will handle the frontend refactor.",
|
|
28
|
+
metadata: { date: "2024-01-15", attendees: ["Alice", "Bob"] }
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await mv.put({
|
|
32
|
+
title: "Technical Decision",
|
|
33
|
+
label: "architecture",
|
|
34
|
+
text: "Decided to use PostgreSQL for the main database. Redis for caching.",
|
|
27
35
|
});
|
|
28
36
|
|
|
29
37
|
// Search by keyword
|
|
30
|
-
const results = await mv.find("
|
|
38
|
+
const results = await mv.find("database");
|
|
31
39
|
console.log(results.hits);
|
|
32
40
|
|
|
33
|
-
// Ask a question
|
|
34
|
-
const answer = await mv.ask("What
|
|
35
|
-
|
|
41
|
+
// Ask a question
|
|
42
|
+
const answer = await mv.ask("What database are we using?", {
|
|
43
|
+
model: "openai:gpt-4o-mini"
|
|
44
|
+
});
|
|
45
|
+
console.log(answer.text);
|
|
36
46
|
|
|
37
|
-
//
|
|
47
|
+
// Close the file
|
|
38
48
|
await mv.seal();
|
|
39
49
|
```
|
|
40
50
|
|
|
41
51
|
## Core API
|
|
42
52
|
|
|
43
|
-
### Opening
|
|
53
|
+
### Opening and Creating
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
import { create, use } from "@memvid/sdk";
|
|
57
|
+
|
|
58
|
+
// Create a new memory file
|
|
59
|
+
const mv = await create("notes.mv2");
|
|
60
|
+
|
|
61
|
+
// Open an existing file
|
|
62
|
+
const mv = await use("basic", "notes.mv2", { mode: "open" });
|
|
44
63
|
|
|
45
|
-
|
|
46
|
-
const mv = await use(
|
|
64
|
+
// Create or open (auto mode)
|
|
65
|
+
const mv = await use("basic", "notes.mv2", { mode: "auto" });
|
|
66
|
+
|
|
67
|
+
// Open read-only
|
|
68
|
+
const mv = await use("basic", "notes.mv2", { readOnly: true });
|
|
47
69
|
```
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| `options.mode` | `string` | `"open"` (default), `"create"`, or `"auto"` |
|
|
54
|
-
| `options.enableLex` | `boolean` | Enable lexical index (default: `true`) |
|
|
55
|
-
| `options.enableVec` | `boolean` | Enable vector index (default: `true`) |
|
|
56
|
-
| `options.readOnly` | `boolean` | Open in read-only mode (default: `false`) |
|
|
57
|
-
| `options.lockTimeoutMs` | `number` | Lock acquisition timeout (ms) |
|
|
58
|
-
| `options.force` | `"stale_only"` | Force-open when a stale lock exists |
|
|
59
|
-
| `options.forceWritable` | `boolean` | Force writable open (dangerous) |
|
|
60
|
-
| `options.memvidApiKey` | `string` | Memvid API key for capacity beyond free tier (`mv2_*`) |
|
|
61
|
-
|
|
62
|
-
### Storing documents
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
71
|
+
### Storing Documents
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// Store text content
|
|
65
75
|
await mv.put({
|
|
66
|
-
title: "
|
|
67
|
-
label: "
|
|
68
|
-
text: "
|
|
69
|
-
metadata: {
|
|
70
|
-
|
|
71
|
-
tags: ["tag1", "tag2"],
|
|
76
|
+
title: "Meeting Notes",
|
|
77
|
+
label: "meeting",
|
|
78
|
+
text: "Discussed the new API design.",
|
|
79
|
+
metadata: { date: "2024-01-15", priority: "high" },
|
|
80
|
+
tags: ["api", "design", "q1"]
|
|
72
81
|
});
|
|
73
|
-
```
|
|
74
82
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
// Store a file (PDF, DOCX, TXT, etc.)
|
|
84
|
+
await mv.put({
|
|
85
|
+
title: "Q4 Report",
|
|
86
|
+
label: "reports",
|
|
87
|
+
file: "./documents/q4-report.pdf"
|
|
88
|
+
});
|
|
78
89
|
|
|
79
|
-
|
|
90
|
+
// Store with both text and file
|
|
80
91
|
await mv.put({
|
|
81
|
-
title: "
|
|
82
|
-
label: "
|
|
83
|
-
text: "
|
|
84
|
-
|
|
85
|
-
// Optional (defaults to "bge-small")
|
|
86
|
-
embeddingModel: "bge-small", // or "openai-small"
|
|
92
|
+
title: "Contract Summary",
|
|
93
|
+
label: "legal",
|
|
94
|
+
text: "Key terms: 2-year agreement, auto-renewal clause.",
|
|
95
|
+
file: "./contracts/agreement.pdf"
|
|
87
96
|
});
|
|
88
97
|
```
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
- Local embedding models use `fastembed` and cache weights under `MEMVID_MODELS_DIR` (first run may download).
|
|
92
|
-
- OpenAI embedding models require `OPENAI_API_KEY` (and optionally `OPENAI_BASE_URL`).
|
|
93
|
-
- If embeddings cannot be generated, the SDK throws `MV015` (it will not silently ingest without embeddings).
|
|
94
|
-
|
|
95
|
-
### Batch ingestion
|
|
99
|
+
### Batch Ingestion
|
|
96
100
|
|
|
97
|
-
For
|
|
101
|
+
For large imports, `putMany` is significantly faster:
|
|
98
102
|
|
|
99
|
-
```
|
|
100
|
-
const
|
|
101
|
-
{ title: "Doc 1", text: "First document content..." },
|
|
102
|
-
{ title: "Doc 2", text: "Second document content..." },
|
|
103
|
+
```javascript
|
|
104
|
+
const documents = [
|
|
105
|
+
{ title: "Doc 1", label: "notes", text: "First document content..." },
|
|
106
|
+
{ title: "Doc 2", label: "notes", text: "Second document content..." },
|
|
103
107
|
// ... thousands more
|
|
104
108
|
];
|
|
105
109
|
|
|
106
|
-
const frameIds = await mv.putMany(
|
|
107
|
-
console.log(`
|
|
110
|
+
const frameIds = await mv.putMany(documents);
|
|
111
|
+
console.log(`Added ${frameIds.length} documents`);
|
|
108
112
|
```
|
|
109
113
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
await mv.putMany(docs, {
|
|
114
|
-
enableEmbedding: true,
|
|
115
|
-
embeddingModel: "bge-small", // or "openai-small"
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
If you provide **pre-computed embeddings**, also attach the embedding identity so the CLI/SDKs can auto-detect the correct query embedding model later:
|
|
114
|
+
### Searching
|
|
120
115
|
|
|
121
|
-
```
|
|
122
|
-
|
|
116
|
+
```javascript
|
|
117
|
+
// Lexical search (BM25 ranking)
|
|
118
|
+
const results = await mv.find("machine learning", { k: 10 });
|
|
123
119
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
await mv.putMany(
|
|
128
|
-
docs.map((doc, i) => ({
|
|
129
|
-
...doc,
|
|
130
|
-
embedding: vectors[i],
|
|
131
|
-
embeddingIdentity: {
|
|
132
|
-
provider: "openai",
|
|
133
|
-
model: embedder.modelName,
|
|
134
|
-
dimension: embedder.dimension,
|
|
135
|
-
},
|
|
136
|
-
}))
|
|
137
|
-
);
|
|
120
|
+
for (const hit of results.hits) {
|
|
121
|
+
console.log(`${hit.title}: ${hit.snippet}`);
|
|
122
|
+
}
|
|
138
123
|
```
|
|
139
124
|
|
|
140
|
-
|
|
125
|
+
Search options:
|
|
141
126
|
|
|
142
|
-
|
|
127
|
+
| Option | Type | Description |
|
|
128
|
+
|--------|------|-------------|
|
|
129
|
+
| `k` | number | Number of results (default: 10) |
|
|
130
|
+
| `snippetChars` | number | Snippet length (default: 240) |
|
|
131
|
+
| `mode` | string | `"lex"`, `"sem"`, or `"auto"` |
|
|
132
|
+
| `scope` | string | Filter by URI prefix |
|
|
143
133
|
|
|
144
|
-
|
|
145
|
-
import { OpenAIEmbeddings } from "@memvid/sdk";
|
|
134
|
+
### Semantic Search
|
|
146
135
|
|
|
147
|
-
|
|
136
|
+
Semantic search requires embeddings. You can generate them during ingestion:
|
|
148
137
|
|
|
149
|
-
|
|
150
|
-
|
|
138
|
+
```javascript
|
|
139
|
+
// Using local embeddings (bge-small, nomic, etc.)
|
|
140
|
+
await mv.put({
|
|
141
|
+
title: "Document",
|
|
142
|
+
text: "Content here...",
|
|
143
|
+
enableEmbedding: true,
|
|
144
|
+
embeddingModel: "bge-small"
|
|
145
|
+
});
|
|
151
146
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
147
|
+
// Using OpenAI embeddings
|
|
148
|
+
await mv.put({
|
|
149
|
+
title: "Document",
|
|
150
|
+
text: "Content here...",
|
|
151
|
+
enableEmbedding: true,
|
|
152
|
+
embeddingModel: "openai-small" // requires OPENAI_API_KEY
|
|
153
|
+
});
|
|
155
154
|
```
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
- `OpenAIEmbeddings` (`OPENAI_API_KEY`)
|
|
159
|
-
- `CohereEmbeddings` (`COHERE_API_KEY`)
|
|
160
|
-
- `VoyageEmbeddings` (`VOYAGE_API_KEY`)
|
|
161
|
-
- `NvidiaEmbeddings` (`NVIDIA_API_KEY`, default base URL `https://integrate.api.nvidia.com`)
|
|
162
|
-
|
|
163
|
-
Notes:
|
|
164
|
-
- If `embedder` is set, `putMany({ enableEmbedding: true })` is ignored (embeddings are computed in JS).
|
|
165
|
-
- `put()` does not accept pre-computed vectors; use `putMany([singleDoc], { embedder })` for external embeddings.
|
|
156
|
+
Then search semantically:
|
|
166
157
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
const results = await mv.find(query, options?)
|
|
158
|
+
```javascript
|
|
159
|
+
const results = await mv.find("neural networks", { mode: "sem" });
|
|
171
160
|
```
|
|
172
161
|
|
|
173
|
-
|
|
174
|
-
|--------|------|-------------|
|
|
175
|
-
| `mode` | `"lex" \| "sem" \| "auto"` | Search mode (default: `"lex"`). `"sem"` uses vector search. `"auto"` reranks lexical hits when embeddings are available. |
|
|
176
|
-
| `queryEmbedding` | `number[]` | Pre-computed query embedding (offline-safe). If omitted, the SDK tries to auto-detect the embedding model from the `.mv2` and embed the query. |
|
|
177
|
-
| `queryEmbeddingModel` | `string` | Override the query embedding model (e.g. `"openai-small"`, `"bge-small"`). |
|
|
178
|
-
| `k` | `number` | Number of results (default: `10`) |
|
|
179
|
-
| `snippetChars` | `number` | Snippet length (default: `240`) |
|
|
180
|
-
| `scope` | `string` | Filter by URI prefix |
|
|
181
|
-
| `adaptive` | `boolean` | Enable adaptive retrieval (semantic-only) |
|
|
182
|
-
| `minRelevancy` | `number` | Minimum relevancy ratio vs top score (default: `0.5`, adaptive-only) |
|
|
183
|
-
| `maxK` | `number` | Max candidates to consider (default: `100`, adaptive-only) |
|
|
184
|
-
| `adaptiveStrategy` | `"relative" \| "absolute" \| "cliff" \| "elbow" \| "combined"` | Adaptive cutoff strategy (default: `"relative"`, adaptive-only) |
|
|
185
|
-
|
|
186
|
-
### Vector search (pre-computed query embedding)
|
|
187
|
-
|
|
188
|
-
Use `vecSearch()` when you already have a query embedding vector (offline-safe):
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
const queryEmbedding = [/* ... floats ... */];
|
|
192
|
-
const results = await mv.vecSearch("my query", queryEmbedding, { k: 10 });
|
|
193
|
-
console.log(results.hits);
|
|
194
|
-
```
|
|
162
|
+
**Windows users:** Local embedding models (bge-small, nomic, etc.) are not available on Windows due to ONNX runtime limitations. Use OpenAI embeddings instead by setting `OPENAI_API_KEY`.
|
|
195
163
|
|
|
196
|
-
###
|
|
164
|
+
### Question Answering (RAG)
|
|
197
165
|
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
|
|
166
|
+
```javascript
|
|
167
|
+
// Basic RAG query
|
|
168
|
+
const answer = await mv.ask("What did we decide about the database?");
|
|
169
|
+
console.log(answer.text);
|
|
201
170
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
| `queryEmbedding` | `number[]` | Pre-computed query embedding for semantic/hybrid ask (offline-safe). If omitted, the SDK tries to auto-detect the embedding model from the `.mv2` and embed the query. |
|
|
207
|
-
| `queryEmbeddingModel` | `string` | Override the query embedding model (e.g. `"openai-small"`, `"bge-small"`). |
|
|
208
|
-
| `adaptive` | `boolean` | Enable adaptive retrieval (semantic/hybrid only) |
|
|
209
|
-
| `minRelevancy` | `number` | Minimum relevancy ratio vs top score (default: `0.5`, adaptive-only) |
|
|
210
|
-
| `maxK` | `number` | Max candidates to consider (default: `100`, adaptive-only) |
|
|
211
|
-
| `adaptiveStrategy` | `"relative" \| "absolute" \| "cliff" \| "elbow" \| "combined"` | Adaptive cutoff strategy (default: `"relative"`, adaptive-only) |
|
|
212
|
-
|
|
213
|
-
### Best practices: Adaptive retrieval
|
|
214
|
-
|
|
215
|
-
For best search quality, enable adaptive retrieval with the `combined` strategy. This dynamically adjusts result counts based on relevance scores rather than returning a fixed `k`:
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
// Recommended for find()
|
|
219
|
-
const results = await mv.find("your query", {
|
|
220
|
-
mode: "sem", // or "auto"
|
|
221
|
-
adaptive: true,
|
|
222
|
-
adaptiveStrategy: "combined",
|
|
171
|
+
// With specific model
|
|
172
|
+
const answer = await mv.ask("Summarize the meeting notes", {
|
|
173
|
+
model: "openai:gpt-4o-mini",
|
|
174
|
+
k: 6 // number of documents to retrieve
|
|
223
175
|
});
|
|
224
176
|
|
|
225
|
-
//
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
adaptive: true,
|
|
229
|
-
adaptiveStrategy: "combined",
|
|
230
|
-
});
|
|
177
|
+
// Get context only (no LLM synthesis)
|
|
178
|
+
const context = await mv.ask("What was discussed?", { contextOnly: true });
|
|
179
|
+
console.log(context.context); // Retrieved document snippets
|
|
231
180
|
```
|
|
232
181
|
|
|
233
|
-
|
|
182
|
+
### Timeline and Stats
|
|
234
183
|
|
|
235
|
-
|
|
184
|
+
```javascript
|
|
185
|
+
// Get recent entries
|
|
186
|
+
const entries = await mv.timeline({ limit: 20 });
|
|
236
187
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
| `contextOnly` | `boolean` | Skip synthesis, return context only |
|
|
242
|
-
| `returnSources` | `boolean` | Include source metadata in response |
|
|
243
|
-
|
|
244
|
-
### Timeline queries
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
const entries = await mv.timeline({
|
|
248
|
-
limit: 50,
|
|
249
|
-
since: 1704067200, // Unix timestamp
|
|
250
|
-
reverse: true,
|
|
251
|
-
});
|
|
188
|
+
// Get statistics
|
|
189
|
+
const stats = await mv.stats();
|
|
190
|
+
console.log(`Documents: ${stats.frame_count}`);
|
|
191
|
+
console.log(`Size: ${stats.size_bytes} bytes`);
|
|
252
192
|
```
|
|
253
193
|
|
|
254
|
-
###
|
|
194
|
+
### Closing
|
|
255
195
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
196
|
+
Always close the memory when done:
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
await mv.seal();
|
|
259
200
|
```
|
|
260
201
|
|
|
261
|
-
|
|
202
|
+
## External Embeddings
|
|
262
203
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
204
|
+
For more control over embeddings, use external providers:
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
import { create, OpenAIEmbeddings, getEmbedder } from "@memvid/sdk";
|
|
266
208
|
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
const report = await verifyMemvid("notes.mv2", { deep: true });
|
|
209
|
+
// Create memory file
|
|
210
|
+
const mv = await create("knowledge.mv2");
|
|
270
211
|
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
212
|
+
// Initialize embedding provider
|
|
213
|
+
const embedder = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
|
|
214
|
+
|
|
215
|
+
// Prepare documents
|
|
216
|
+
const documents = [
|
|
217
|
+
{ title: "ML Basics", label: "ai", text: "Machine learning enables systems to learn from data." },
|
|
218
|
+
{ title: "Deep Learning", label: "ai", text: "Deep learning uses neural networks with multiple layers." },
|
|
219
|
+
];
|
|
274
220
|
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
await verifySingleFile("notes.mv2");
|
|
221
|
+
// Ingest with external embeddings
|
|
222
|
+
await mv.putMany(documents, { embedder });
|
|
278
223
|
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
224
|
+
// Search using external embeddings
|
|
225
|
+
const results = await mv.find("neural networks", { mode: "sem", k: 3, embedder });
|
|
226
|
+
|
|
227
|
+
for (const hit of results.hits) {
|
|
228
|
+
console.log(`${hit.title}: ${hit.score.toFixed(3)}`);
|
|
229
|
+
}
|
|
283
230
|
```
|
|
284
231
|
|
|
285
|
-
|
|
232
|
+
Built-in providers:
|
|
233
|
+
- `OpenAIEmbeddings` (requires `OPENAI_API_KEY`)
|
|
234
|
+
- `CohereEmbeddings` (requires `COHERE_API_KEY`)
|
|
235
|
+
- `VoyageEmbeddings` (requires `VOYAGE_API_KEY`)
|
|
236
|
+
- `NvidiaEmbeddings` (requires `NVIDIA_API_KEY`)
|
|
237
|
+
- `GeminiEmbeddings` (requires `GOOGLE_API_KEY` or `GEMINI_API_KEY`)
|
|
238
|
+
- `MistralEmbeddings` (requires `MISTRAL_API_KEY`)
|
|
286
239
|
|
|
287
|
-
|
|
240
|
+
Use the factory function for quick setup:
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
import { getEmbedder } from "@memvid/sdk";
|
|
244
|
+
|
|
245
|
+
// Create any supported provider
|
|
246
|
+
const embedder = getEmbedder("openai"); // or "cohere", "voyage", "nvidia", "gemini", "mistral"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Framework Integrations
|
|
288
250
|
|
|
289
251
|
### LangChain
|
|
290
252
|
|
|
291
|
-
```
|
|
253
|
+
```javascript
|
|
292
254
|
import { use } from "@memvid/sdk";
|
|
293
255
|
|
|
294
256
|
const mv = await use("langchain", "notes.mv2");
|
|
295
|
-
const tools = mv.tools;
|
|
257
|
+
const tools = mv.tools; // StructuredTool instances for agents
|
|
296
258
|
```
|
|
297
259
|
|
|
298
260
|
### LlamaIndex
|
|
299
261
|
|
|
300
|
-
```
|
|
262
|
+
```javascript
|
|
301
263
|
const mv = await use("llamaindex", "notes.mv2");
|
|
302
|
-
const
|
|
264
|
+
const engine = mv.asQueryEngine();
|
|
265
|
+
const response = await engine.query("What is the timeline?");
|
|
303
266
|
```
|
|
304
267
|
|
|
305
|
-
### OpenAI
|
|
268
|
+
### OpenAI Function Calling
|
|
306
269
|
|
|
307
|
-
```
|
|
270
|
+
```javascript
|
|
308
271
|
const mv = await use("openai", "notes.mv2");
|
|
309
|
-
const functions = mv.functions;
|
|
272
|
+
const functions = mv.functions; // JSON schemas for tool_calls
|
|
310
273
|
```
|
|
311
274
|
|
|
312
275
|
### Vercel AI SDK
|
|
313
276
|
|
|
314
|
-
```
|
|
277
|
+
```javascript
|
|
315
278
|
const mv = await use("vercel-ai", "notes.mv2");
|
|
316
279
|
```
|
|
317
280
|
|
|
318
|
-
##
|
|
319
|
-
|
|
320
|
-
Extract structured tables from PDFs:
|
|
281
|
+
## Error Handling
|
|
321
282
|
|
|
322
|
-
|
|
323
|
-
const result = await mv.putPdfTables("report.pdf", true);
|
|
324
|
-
console.log(`Extracted ${result.tables_count} tables`);
|
|
283
|
+
Errors include a code for programmatic handling:
|
|
325
284
|
|
|
326
|
-
|
|
327
|
-
const data = await mv.getTable(tables[0].table_id, "json");
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Error handling
|
|
331
|
-
|
|
332
|
-
Errors include a code prefix for programmatic handling:
|
|
333
|
-
|
|
334
|
-
| Code | Description |
|
|
335
|
-
|------|-------------|
|
|
336
|
-
| `MV001` | Storage capacity exceeded |
|
|
337
|
-
| `MV002` | Invalid ticket signature |
|
|
338
|
-
| `MV003` | Ticket replay detected |
|
|
339
|
-
| `MV004` | Lexical index not enabled |
|
|
340
|
-
| `MV005` | Time index missing |
|
|
341
|
-
| `MV006` | Verification failed |
|
|
342
|
-
| `MV007` | File locked by another process |
|
|
343
|
-
| `MV008` | Memvid API key required |
|
|
344
|
-
| `MV009` | Memory already bound |
|
|
345
|
-
| `MV010` | Frame not found |
|
|
346
|
-
| `MV011` | Vector index not enabled |
|
|
347
|
-
| `MV012` | Corrupt file detected |
|
|
348
|
-
| `MV013` | I/O error (e.g., file not found) |
|
|
349
|
-
| `MV014` | Vector dimension mismatch |
|
|
350
|
-
| `MV015` | Embedding runtime unavailable/failed |
|
|
351
|
-
| `MV999` | Unknown/internal error |
|
|
352
|
-
|
|
353
|
-
```typescript
|
|
285
|
+
```javascript
|
|
354
286
|
import { MemvidError } from "@memvid/sdk";
|
|
355
287
|
|
|
356
288
|
try {
|
|
357
|
-
await mv.put({
|
|
289
|
+
await mv.put({ title: "Doc", text: "Content" });
|
|
358
290
|
} catch (err) {
|
|
359
291
|
if (err instanceof MemvidError) {
|
|
360
|
-
|
|
361
|
-
console.error("
|
|
362
|
-
|
|
363
|
-
console.error(
|
|
292
|
+
switch (err.code) {
|
|
293
|
+
case "MV001": console.error("Storage capacity exceeded"); break;
|
|
294
|
+
case "MV007": console.error("File is locked"); break;
|
|
295
|
+
case "MV015": console.error("Embedding failed"); break;
|
|
296
|
+
default: console.error(`Error ${err.code}: ${err.message}`);
|
|
364
297
|
}
|
|
365
298
|
}
|
|
366
299
|
}
|
|
367
300
|
```
|
|
368
301
|
|
|
369
|
-
|
|
302
|
+
Common error codes:
|
|
370
303
|
|
|
371
|
-
|
|
|
372
|
-
|
|
373
|
-
|
|
|
374
|
-
|
|
|
375
|
-
|
|
|
376
|
-
|
|
|
377
|
-
|
|
|
378
|
-
| `OPENAI_BASE_URL` | Override OpenAI API base URL (defaults to `https://api.openai.com`) |
|
|
304
|
+
| Code | Description |
|
|
305
|
+
|------|-------------|
|
|
306
|
+
| MV001 | Storage capacity exceeded |
|
|
307
|
+
| MV007 | File locked by another process |
|
|
308
|
+
| MV010 | Frame not found |
|
|
309
|
+
| MV013 | File not found |
|
|
310
|
+
| MV015 | Embedding failed |
|
|
379
311
|
|
|
380
|
-
##
|
|
312
|
+
## Environment Variables
|
|
381
313
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
314
|
+
| Variable | Description |
|
|
315
|
+
|----------|-------------|
|
|
316
|
+
| `OPENAI_API_KEY` | For OpenAI embeddings and LLM synthesis |
|
|
317
|
+
| `OPENAI_BASE_URL` | Custom OpenAI-compatible endpoint |
|
|
318
|
+
| `NVIDIA_API_KEY` | For NVIDIA NIM embeddings |
|
|
319
|
+
| `MEMVID_MODELS_DIR` | Local embedding model cache directory |
|
|
320
|
+
| `MEMVID_API_KEY` | For capacity beyond the free tier |
|
|
321
|
+
| `MEMVID_OFFLINE` | Set to `1` to disable network features |
|
|
322
|
+
|
|
323
|
+
## Platform Support
|
|
324
|
+
|
|
325
|
+
| Platform | Architecture | Local Embeddings |
|
|
326
|
+
|----------|--------------|------------------|
|
|
327
|
+
| macOS | ARM64 (Apple Silicon) | Yes |
|
|
328
|
+
| macOS | x64 (Intel) | Yes |
|
|
329
|
+
| Linux | x64 (glibc) | Yes |
|
|
330
|
+
| Windows | x64 | No (use OpenAI) |
|
|
385
331
|
|
|
386
|
-
|
|
387
|
-
pnpm run build
|
|
332
|
+
## Requirements
|
|
388
333
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
cp target/release/libmemvid_node.dylib index.node # macOS
|
|
392
|
-
```
|
|
334
|
+
- Node.js 18 or later
|
|
335
|
+
- For local embeddings: macOS or Linux (Windows requires OpenAI)
|
|
393
336
|
|
|
394
|
-
##
|
|
337
|
+
## More Information
|
|
395
338
|
|
|
396
|
-
-
|
|
397
|
-
-
|
|
339
|
+
- Documentation: https://docs.memvid.com
|
|
340
|
+
- GitHub: https://github.com/memvid/memvid
|
|
341
|
+
- Discord: https://discord.gg/2mynS7fcK7
|
|
342
|
+
- Website: https://memvid.com
|
|
398
343
|
|
|
399
344
|
## License
|
|
400
345
|
|
|
401
|
-
Apache-2.0
|
|
346
|
+
Apache-2.0
|
package/dist/index.js
CHANGED
|
@@ -488,16 +488,26 @@ function loadNativeAddon() {
|
|
|
488
488
|
}
|
|
489
489
|
// Production mode: load from platform-specific package
|
|
490
490
|
if (platformInfo) {
|
|
491
|
+
// Split scoped package name: "@memvid/sdk-win32-x64-msvc" -> ["@memvid", "sdk-win32-x64-msvc"]
|
|
492
|
+
const pkgParts = platformInfo.pkg.split("/");
|
|
493
|
+
const scope = pkgParts[0]; // "@memvid"
|
|
494
|
+
const pkgName = pkgParts[1]; // "sdk-win32-x64-msvc"
|
|
491
495
|
// Try to find the platform package in various locations
|
|
492
496
|
const possiblePaths = [
|
|
493
|
-
//
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
+
// Sibling in same scope (most common for scoped packages)
|
|
498
|
+
// From @memvid/sdk/dist -> @memvid/sdk-win32-x64-msvc
|
|
499
|
+
path.join(__dirname, "..", "..", pkgName, platformInfo.binary),
|
|
500
|
+
// Standard npm install location (nested node_modules)
|
|
501
|
+
path.join(__dirname, "..", "node_modules", scope, pkgName, platformInfo.binary),
|
|
497
502
|
// Hoisted to root node_modules
|
|
498
|
-
|
|
503
|
+
// From @memvid/sdk/dist -> ../../.. = node_modules, then @memvid/sdk-win32-x64-msvc
|
|
504
|
+
path.join(__dirname, "..", "..", "..", scope, pkgName, platformInfo.binary),
|
|
505
|
+
// Hoisted 4 levels up (deep yarn workspaces)
|
|
506
|
+
path.join(__dirname, "..", "..", "..", "..", scope, pkgName, platformInfo.binary),
|
|
499
507
|
// pnpm structure
|
|
500
|
-
path.join(__dirname, "..", "..", ".pnpm", "node_modules",
|
|
508
|
+
path.join(__dirname, "..", "..", ".pnpm", "node_modules", scope, pkgName, platformInfo.binary),
|
|
509
|
+
// Yarn PnP / berry
|
|
510
|
+
path.join(__dirname, "..", "..", ".yarn", "cache", `${scope.replace("@", "")}-${pkgName}`, platformInfo.binary),
|
|
501
511
|
];
|
|
502
512
|
for (const binaryPath of possiblePaths) {
|
|
503
513
|
try {
|
|
@@ -542,6 +552,17 @@ function loadNativeAddon() {
|
|
|
542
552
|
}
|
|
543
553
|
// No platform package found
|
|
544
554
|
const supportedPlatforms = Object.keys(platformPackages).join(", ");
|
|
555
|
+
const platformPkg = platformInfo?.pkg;
|
|
556
|
+
if (platformPkg) {
|
|
557
|
+
// Platform is supported but binary not found
|
|
558
|
+
throw new Error(`Native binary not found for platform: ${key}\n` +
|
|
559
|
+
`The platform package ${platformPkg} may not have installed correctly.\n` +
|
|
560
|
+
`Try reinstalling:\n` +
|
|
561
|
+
` npm install ${platformPkg}\n` +
|
|
562
|
+
` # or: yarn add ${platformPkg}\n` +
|
|
563
|
+
`Then reinstall the main package:\n` +
|
|
564
|
+
` npm install @memvid/sdk`);
|
|
565
|
+
}
|
|
545
566
|
throw new Error(`Unsupported platform: ${key}\n` +
|
|
546
567
|
`Supported platforms: ${supportedPlatforms}\n` +
|
|
547
568
|
`Make sure you have installed @memvid/sdk correctly:\n` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memvid/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.142",
|
|
4
4
|
"description": "Single-file AI memory system for Node.js. Store, search, and query documents with built-in RAG.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@memvid/sdk-darwin-arm64": "2.0.
|
|
45
|
-
"@memvid/sdk-darwin-x64": "2.0.
|
|
46
|
-
"@memvid/sdk-linux-x64-gnu": "2.0.
|
|
47
|
-
"@memvid/sdk-win32-x64-msvc": "2.0.
|
|
44
|
+
"@memvid/sdk-darwin-arm64": "2.0.142",
|
|
45
|
+
"@memvid/sdk-darwin-x64": "2.0.142",
|
|
46
|
+
"@memvid/sdk-linux-x64-gnu": "2.0.142",
|
|
47
|
+
"@memvid/sdk-win32-x64-msvc": "2.0.142"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@langchain/core": ">=0.3.0",
|