@danielzfliu/memory 2.0.0 → 2.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/README.md +9 -351
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +314 -44
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +6 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +43 -14
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +9 -0
- package/docs/configuration.md +55 -0
- package/docs/getting-started.md +71 -0
- package/docs/mcp-server.md +61 -0
- package/docs/npm-package.md +100 -0
- package/docs/rest-api.md +455 -0
- package/package.json +3 -1
package/docs/rest-api.md
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
# REST API
|
|
2
|
+
|
|
3
|
+
Use Memory as a standalone HTTP service.
|
|
4
|
+
|
|
5
|
+
## Start the server
|
|
6
|
+
|
|
7
|
+
After completing [Getting Started](./getting-started.md):
|
|
8
|
+
|
|
9
|
+
### Development
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm run dev:http
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Production-style run
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm run build
|
|
19
|
+
npm run start:http
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The server listens on `http://localhost:3000` by default. Set `PORT` to change it.
|
|
23
|
+
|
|
24
|
+
See [Configuration](./configuration.md) for runtime options such as CORS and request logging.
|
|
25
|
+
|
|
26
|
+
## API contract
|
|
27
|
+
|
|
28
|
+
Base URL: `http://localhost:3000`
|
|
29
|
+
|
|
30
|
+
All request bodies are JSON. Success responses are also JSON unless the status is `204 No Content`.
|
|
31
|
+
|
|
32
|
+
### Shared response shapes
|
|
33
|
+
|
|
34
|
+
`Piece`
|
|
35
|
+
|
|
36
|
+
| Field | Type | Description |
|
|
37
|
+
|------|------|-------------|
|
|
38
|
+
| `id` | `string` | Server-generated UUID |
|
|
39
|
+
| `content` | `string` | Stored text content |
|
|
40
|
+
| `title` | `string` | Optional human-readable title |
|
|
41
|
+
| `tags` | `string[]` | Tags associated with the piece |
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"id": "2f7b8d6a-0f34-4a1f-85c0-5a7f4cce7c4d",
|
|
48
|
+
"title": "TypeScript overview",
|
|
49
|
+
"content": "TypeScript is a typed superset of JavaScript.",
|
|
50
|
+
"tags": ["typescript", "programming"]
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`QueryResult`
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"piece": {
|
|
59
|
+
"id": "2f7b8d6a-0f34-4a1f-85c0-5a7f4cce7c4d",
|
|
60
|
+
"title": "TypeScript overview",
|
|
61
|
+
"content": "TypeScript is a typed superset of JavaScript.",
|
|
62
|
+
"tags": ["typescript", "programming"]
|
|
63
|
+
},
|
|
64
|
+
"score": 0.87
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`RagResult`
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"answer": "TypeScript adds a type system on top of JavaScript. [1]",
|
|
73
|
+
"sources": [
|
|
74
|
+
{
|
|
75
|
+
"piece": {
|
|
76
|
+
"id": "2f7b8d6a-0f34-4a1f-85c0-5a7f4cce7c4d",
|
|
77
|
+
"title": "TypeScript overview",
|
|
78
|
+
"content": "TypeScript is a typed superset of JavaScript.",
|
|
79
|
+
"tags": ["typescript", "programming"]
|
|
80
|
+
},
|
|
81
|
+
"score": 0.87
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`ErrorResponse`
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"error": "content (string) is required"
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`ServiceUnavailableResponse`
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"error": "Failed to connect to ChromaDB",
|
|
100
|
+
"details": "Error: ..."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`HealthResponse`
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"status": "ok",
|
|
109
|
+
"services": {
|
|
110
|
+
"api": {
|
|
111
|
+
"status": "ok"
|
|
112
|
+
},
|
|
113
|
+
"chromadb": {
|
|
114
|
+
"status": "ok"
|
|
115
|
+
},
|
|
116
|
+
"ollama": {
|
|
117
|
+
"status": "ok",
|
|
118
|
+
"modelCount": 7
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
> **Multi-collection:** All piece and query endpoints accept an optional `collection` parameter to target a specific collection. For `POST` and `PUT`, pass it in the JSON body. For `GET` and `DELETE`, pass it as a query parameter. Omitting it uses the default collection.
|
|
125
|
+
|
|
126
|
+
### `GET /health`
|
|
127
|
+
|
|
128
|
+
Report the health of the API, ChromaDB, and Ollama.
|
|
129
|
+
|
|
130
|
+
Responses:
|
|
131
|
+
|
|
132
|
+
| Status | Body |
|
|
133
|
+
|--------|------|
|
|
134
|
+
| `200` | `HealthResponse` with `status: "ok"` |
|
|
135
|
+
| `503` | `HealthResponse` with `status: "degraded"` |
|
|
136
|
+
|
|
137
|
+
Notes:
|
|
138
|
+
|
|
139
|
+
| Field | Description |
|
|
140
|
+
|------|-------------|
|
|
141
|
+
| `services.api.status` | Always `ok` when the API process is responding |
|
|
142
|
+
| `services.chromadb.status` | `ok` when ChromaDB is reachable |
|
|
143
|
+
| `services.ollama.status` | `ok` when Ollama responds successfully to `/api/tags` |
|
|
144
|
+
| `services.ollama.modelCount` | Present when the Ollama health check returns a model list |
|
|
145
|
+
|
|
146
|
+
Example:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
curl http://localhost:3000/health
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `GET /pieces`
|
|
153
|
+
|
|
154
|
+
List pieces from a collection, optionally paginated.
|
|
155
|
+
|
|
156
|
+
Query parameters:
|
|
157
|
+
|
|
158
|
+
| Name | Type | Required | Description |
|
|
159
|
+
|------|------|----------|-------------|
|
|
160
|
+
| `collection` | `string` | No | Optional target collection |
|
|
161
|
+
| `limit` | `number` | No | Positive integer maximum number of pieces to return |
|
|
162
|
+
| `offset` | `number` | No | Non-negative integer number of pieces to skip |
|
|
163
|
+
|
|
164
|
+
Responses:
|
|
165
|
+
|
|
166
|
+
| Status | Body |
|
|
167
|
+
|--------|------|
|
|
168
|
+
| `200` | `{ "pieces": Piece[] }` |
|
|
169
|
+
| `400` | `ErrorResponse` |
|
|
170
|
+
| `500` | `ErrorResponse` |
|
|
171
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
curl http://localhost:3000/pieces
|
|
177
|
+
curl "http://localhost:3000/pieces?collection=agent-alice&limit=20&offset=40"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `GET /tags`
|
|
181
|
+
|
|
182
|
+
List unique tags from a collection in sorted order.
|
|
183
|
+
|
|
184
|
+
Query parameters:
|
|
185
|
+
|
|
186
|
+
| Name | Type | Required | Description |
|
|
187
|
+
|------|------|----------|-------------|
|
|
188
|
+
| `collection` | `string` | No | Optional target collection |
|
|
189
|
+
| `limit` | `number` | No | Positive integer maximum number of tags to return |
|
|
190
|
+
| `offset` | `number` | No | Non-negative integer number of tags to skip |
|
|
191
|
+
|
|
192
|
+
Responses:
|
|
193
|
+
|
|
194
|
+
| Status | Body |
|
|
195
|
+
|--------|------|
|
|
196
|
+
| `200` | `{ "tags": string[] }` |
|
|
197
|
+
| `400` | `ErrorResponse` |
|
|
198
|
+
| `500` | `ErrorResponse` |
|
|
199
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
curl http://localhost:3000/tags
|
|
205
|
+
curl "http://localhost:3000/tags?collection=agent-alice&limit=25&offset=0"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### `POST /pieces`
|
|
209
|
+
|
|
210
|
+
Create a new piece.
|
|
211
|
+
|
|
212
|
+
Request body:
|
|
213
|
+
|
|
214
|
+
| Field | Type | Required | Description |
|
|
215
|
+
|------|------|----------|-------------|
|
|
216
|
+
| `content` | `string` | Yes | Piece text to store |
|
|
217
|
+
| `title` | `string` | No | Optional title |
|
|
218
|
+
| `tags` | `string[]` | No | Optional tags; defaults to `[]` |
|
|
219
|
+
| `collection` | `string` | No | Optional target collection |
|
|
220
|
+
|
|
221
|
+
Responses:
|
|
222
|
+
|
|
223
|
+
| Status | Body |
|
|
224
|
+
|--------|------|
|
|
225
|
+
| `201` | `Piece` |
|
|
226
|
+
| `400` | `ErrorResponse` |
|
|
227
|
+
| `500` | `ErrorResponse` |
|
|
228
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
229
|
+
|
|
230
|
+
Example:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
curl -X POST http://localhost:3000/pieces \
|
|
234
|
+
-H "Content-Type: application/json" \
|
|
235
|
+
-d '{"title": "TypeScript overview", "content": "TypeScript is a typed superset of JavaScript.", "tags": ["typescript", "programming"]}'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### `GET /pieces/:id`
|
|
239
|
+
|
|
240
|
+
Fetch a piece by ID.
|
|
241
|
+
|
|
242
|
+
Query parameters:
|
|
243
|
+
|
|
244
|
+
| Name | Type | Required | Description |
|
|
245
|
+
|------|------|----------|-------------|
|
|
246
|
+
| `collection` | `string` | No | Optional target collection |
|
|
247
|
+
|
|
248
|
+
Responses:
|
|
249
|
+
|
|
250
|
+
| Status | Body |
|
|
251
|
+
|--------|------|
|
|
252
|
+
| `200` | `Piece` |
|
|
253
|
+
| `404` | `ErrorResponse` with `"Piece not found"` |
|
|
254
|
+
| `500` | `ErrorResponse` |
|
|
255
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
256
|
+
|
|
257
|
+
Example:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
curl http://localhost:3000/pieces/<id>
|
|
261
|
+
curl http://localhost:3000/pieces/<id>?collection=agent-alice
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### `PUT /pieces/:id`
|
|
265
|
+
|
|
266
|
+
Update an existing piece. Any omitted field keeps its current value.
|
|
267
|
+
|
|
268
|
+
Request body:
|
|
269
|
+
|
|
270
|
+
| Field | Type | Required | Description |
|
|
271
|
+
|------|------|----------|-------------|
|
|
272
|
+
| `content` | `string` | No | Updated piece content |
|
|
273
|
+
| `title` | `string \| null` | No | Updated title; pass `null` to clear it |
|
|
274
|
+
| `tags` | `string[]` | No | Replacement tag list |
|
|
275
|
+
| `collection` | `string` | No | Optional target collection |
|
|
276
|
+
|
|
277
|
+
Responses:
|
|
278
|
+
|
|
279
|
+
| Status | Body |
|
|
280
|
+
|--------|------|
|
|
281
|
+
| `200` | `Piece` |
|
|
282
|
+
| `400` | `ErrorResponse` |
|
|
283
|
+
| `404` | `ErrorResponse` with `"Piece not found"` |
|
|
284
|
+
| `500` | `ErrorResponse` |
|
|
285
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
286
|
+
|
|
287
|
+
Example:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
curl -X PUT http://localhost:3000/pieces/<id> \
|
|
291
|
+
-H "Content-Type: application/json" \
|
|
292
|
+
-d '{"title": "Updated title", "content": "Updated content.", "tags": ["new-tag"]}'
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### `DELETE /pieces/:id`
|
|
296
|
+
|
|
297
|
+
Delete a piece by ID.
|
|
298
|
+
|
|
299
|
+
Query parameters:
|
|
300
|
+
|
|
301
|
+
| Name | Type | Required | Description |
|
|
302
|
+
|------|------|----------|-------------|
|
|
303
|
+
| `collection` | `string` | No | Optional target collection |
|
|
304
|
+
|
|
305
|
+
Responses:
|
|
306
|
+
|
|
307
|
+
| Status | Body |
|
|
308
|
+
|--------|------|
|
|
309
|
+
| `204` | No body |
|
|
310
|
+
| `500` | `ErrorResponse` |
|
|
311
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
312
|
+
|
|
313
|
+
Example:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
curl -X DELETE http://localhost:3000/pieces/<id>
|
|
317
|
+
curl -X DELETE http://localhost:3000/pieces/<id>?collection=agent-alice
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### `POST /query`
|
|
321
|
+
|
|
322
|
+
Run semantic search over stored pieces.
|
|
323
|
+
|
|
324
|
+
Request body:
|
|
325
|
+
|
|
326
|
+
| Field | Type | Required | Description |
|
|
327
|
+
|------|------|----------|-------------|
|
|
328
|
+
| `query` | `string` | Yes | Search query |
|
|
329
|
+
| `tags` | `string[]` | No | Restrict matches to pieces containing these tags |
|
|
330
|
+
| `topK` | `number` | No | Positive integer result count; defaults to `10` |
|
|
331
|
+
| `useHybridSearch` | `boolean` | No | When `true`, combine vector and keyword ranking |
|
|
332
|
+
| `collection` | `string` | No | Optional target collection |
|
|
333
|
+
|
|
334
|
+
Responses:
|
|
335
|
+
|
|
336
|
+
| Status | Body |
|
|
337
|
+
|--------|------|
|
|
338
|
+
| `200` | `QueryResult[]` |
|
|
339
|
+
| `400` | `ErrorResponse` |
|
|
340
|
+
| `500` | `ErrorResponse` |
|
|
341
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
342
|
+
|
|
343
|
+
Example:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
curl -X POST http://localhost:3000/query \
|
|
347
|
+
-H "Content-Type: application/json" \
|
|
348
|
+
-d '{"query": "What is TypeScript?", "topK": 5}'
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
With tag filtering:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
curl -X POST http://localhost:3000/query \
|
|
355
|
+
-H "Content-Type: application/json" \
|
|
356
|
+
-d '{"query": "What is TypeScript?", "tags": ["programming"], "topK": 5}'
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
With hybrid search:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
curl -X POST http://localhost:3000/query \
|
|
363
|
+
-H "Content-Type: application/json" \
|
|
364
|
+
-d '{"query": "What is TypeScript?", "topK": 5, "useHybridSearch": true}'
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### `POST /rag`
|
|
368
|
+
|
|
369
|
+
Run retrieval and then ask the configured generation model to answer using only the retrieved context.
|
|
370
|
+
|
|
371
|
+
Request body:
|
|
372
|
+
|
|
373
|
+
| Field | Type | Required | Description |
|
|
374
|
+
|------|------|----------|-------------|
|
|
375
|
+
| `query` | `string` | Yes | User question |
|
|
376
|
+
| `tags` | `string[]` | No | Restrict retrieval to matching tags |
|
|
377
|
+
| `topK` | `number` | No | Positive integer source count; defaults to `10` |
|
|
378
|
+
| `useHybridSearch` | `boolean` | No | When `true`, combine vector and keyword ranking before generation |
|
|
379
|
+
| `collection` | `string` | No | Optional target collection |
|
|
380
|
+
|
|
381
|
+
Responses:
|
|
382
|
+
|
|
383
|
+
| Status | Body |
|
|
384
|
+
|--------|------|
|
|
385
|
+
| `200` | `RagResult` |
|
|
386
|
+
| `400` | `ErrorResponse` |
|
|
387
|
+
| `500` | `ErrorResponse` |
|
|
388
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
389
|
+
|
|
390
|
+
Example:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
curl -X POST http://localhost:3000/rag \
|
|
394
|
+
-H "Content-Type: application/json" \
|
|
395
|
+
-d '{"query": "Explain TypeScript", "tags": ["programming"], "topK": 5}'
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
If no relevant pieces are found, the server still returns `200` with an answer explaining that there is not enough context and `sources: []`.
|
|
399
|
+
|
|
400
|
+
### `GET /collections`
|
|
401
|
+
|
|
402
|
+
List available collections.
|
|
403
|
+
|
|
404
|
+
Responses:
|
|
405
|
+
|
|
406
|
+
| Status | Body |
|
|
407
|
+
|--------|------|
|
|
408
|
+
| `200` | `{ "collections": string[] }` |
|
|
409
|
+
| `500` | `ErrorResponse` |
|
|
410
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
curl http://localhost:3000/collections
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### `PUT /collections/:name`
|
|
419
|
+
|
|
420
|
+
Ensure a collection exists.
|
|
421
|
+
|
|
422
|
+
This endpoint is idempotent and returns success whether the collection is newly created or already present.
|
|
423
|
+
|
|
424
|
+
Responses:
|
|
425
|
+
|
|
426
|
+
| Status | Body |
|
|
427
|
+
|--------|------|
|
|
428
|
+
| `204` | No body |
|
|
429
|
+
| `400` | `ErrorResponse` |
|
|
430
|
+
| `500` | `ErrorResponse` |
|
|
431
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
432
|
+
|
|
433
|
+
Example:
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
curl -X PUT http://localhost:3000/collections/agent-alice
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### `DELETE /collections/:name`
|
|
440
|
+
|
|
441
|
+
Delete a collection by name.
|
|
442
|
+
|
|
443
|
+
Responses:
|
|
444
|
+
|
|
445
|
+
| Status | Body |
|
|
446
|
+
|--------|------|
|
|
447
|
+
| `204` | No body |
|
|
448
|
+
| `500` | `ErrorResponse` |
|
|
449
|
+
| `503` | `ServiceUnavailableResponse` |
|
|
450
|
+
|
|
451
|
+
Example:
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
curl -X DELETE http://localhost:3000/collections/agent-alice
|
|
455
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielzfliu/memory",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A local MCP server and Node.js library for storing, searching, and querying tagged text pieces using ChromaDB and Ollama",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
|
+
"docs",
|
|
18
19
|
"README.md",
|
|
19
20
|
"LICENSE"
|
|
20
21
|
],
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"@types/express": "^5.0.0",
|
|
67
68
|
"@types/supertest": "^6.0.3",
|
|
68
69
|
"@types/uuid": "^10.0.0",
|
|
70
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
69
71
|
"supertest": "^7.2.2",
|
|
70
72
|
"tsx": "^4.19.0",
|
|
71
73
|
"typescript": "^5.6.0",
|