@lumi0/sdk 0.0.3 → 0.0.5
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 +666 -59
- package/dist/index.d.mts +93 -9
- package/dist/index.mjs +31 -9
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,146 +1,753 @@
|
|
|
1
1
|
# Lumi0 TypeScript SDK
|
|
2
2
|
|
|
3
|
-
The official TypeScript SDK for
|
|
4
|
-
|
|
3
|
+
The official TypeScript SDK for [Lumi0](https://lumi0.com), an AI infrastructure platform for persistent memory, context compression, and document ingestion.
|
|
4
|
+
|
|
5
|
+
Lumi0 gives AI applications long-term memory: store information about users, retrieve relevant context with semantic search, manage memory versions, batch-write memories, forget stored information, upload documents from URLs, and compress large contexts before sending them to an LLM.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
* Persistent AI memory
|
|
10
|
+
* Semantic memory search
|
|
11
|
+
* Memory versioning
|
|
12
|
+
* Batch memory storage
|
|
13
|
+
* Memory deduplication
|
|
14
|
+
* Context compression
|
|
15
|
+
* Fixed and adaptive compression modes
|
|
16
|
+
* URL-based document ingestion
|
|
17
|
+
* Automatic document type detection
|
|
18
|
+
* TypeScript-first API
|
|
19
|
+
* Bun and Node.js compatible
|
|
20
|
+
* Configurable API URL and request timeout
|
|
5
21
|
|
|
6
22
|
## Installation
|
|
7
23
|
|
|
24
|
+
### Bun
|
|
25
|
+
|
|
8
26
|
```bash
|
|
9
27
|
bun add @lumi0/sdk
|
|
10
28
|
```
|
|
11
29
|
|
|
30
|
+
### npm
|
|
31
|
+
|
|
12
32
|
```bash
|
|
13
33
|
npm install @lumi0/sdk
|
|
14
34
|
```
|
|
15
35
|
|
|
16
|
-
##
|
|
36
|
+
## Requirements
|
|
17
37
|
|
|
18
|
-
|
|
38
|
+
* Node.js 18+ or Bun
|
|
39
|
+
* A Lumi0 API key
|
|
40
|
+
|
|
41
|
+
Set your API key as an environment variable:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
LUMI0_API_KEY=your_api_key
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Never expose your Lumi0 API key in browser-side code. Keep it on your server or in a trusted backend environment.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
Create a Lumi0 client:
|
|
19
52
|
|
|
20
53
|
```ts
|
|
21
54
|
import { Lumi0 } from "@lumi0/sdk";
|
|
22
55
|
|
|
23
56
|
const client = new Lumi0({
|
|
24
|
-
|
|
57
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
25
58
|
});
|
|
26
59
|
```
|
|
27
60
|
|
|
28
|
-
Store a memory
|
|
61
|
+
### Store a memory
|
|
62
|
+
|
|
63
|
+
Store information associated with an identifier:
|
|
29
64
|
|
|
30
65
|
```ts
|
|
31
66
|
await client.store({
|
|
32
|
-
|
|
33
|
-
|
|
67
|
+
id: "user_123",
|
|
68
|
+
content: "The user prefers concise TypeScript examples.",
|
|
34
69
|
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Search memories
|
|
35
73
|
|
|
74
|
+
Retrieve memories that are semantically relevant to a query:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
36
77
|
const memories = await client.search({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
78
|
+
id: "user_123",
|
|
79
|
+
query: "What coding examples does the user prefer?",
|
|
80
|
+
limit: 5,
|
|
40
81
|
});
|
|
82
|
+
|
|
83
|
+
console.log(memories);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Upload a document
|
|
87
|
+
|
|
88
|
+
Upload a document directly from a URL:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const upload = await client.files({
|
|
92
|
+
url: "https://example.com/document.pdf",
|
|
93
|
+
id: "tenant_123",
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `id` identifies the tenant or external entity the uploaded document belongs to. It can be either a Lumi0 tenant ID or your own external ID.
|
|
98
|
+
|
|
99
|
+
A common AI application flow looks like:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
User
|
|
103
|
+
↓
|
|
104
|
+
Your AI Application
|
|
105
|
+
↓
|
|
106
|
+
Lumi0
|
|
107
|
+
├── Memory
|
|
108
|
+
├── File Ingestion
|
|
109
|
+
└── Context Compression
|
|
110
|
+
↓
|
|
111
|
+
Relevant Context
|
|
112
|
+
↓
|
|
113
|
+
LLM
|
|
114
|
+
↓
|
|
115
|
+
Response
|
|
41
116
|
```
|
|
42
117
|
|
|
43
|
-
## API
|
|
118
|
+
## API Reference
|
|
44
119
|
|
|
45
|
-
### `store`
|
|
120
|
+
### `store()`
|
|
46
121
|
|
|
47
|
-
Stores
|
|
122
|
+
Stores a single memory for an identifier.
|
|
48
123
|
|
|
49
124
|
```ts
|
|
50
125
|
await client.store({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
dedupeThreshold: 0.9,
|
|
126
|
+
id: "user_123",
|
|
127
|
+
content: "The user uses Bun and TypeScript.",
|
|
54
128
|
});
|
|
55
129
|
```
|
|
56
130
|
|
|
57
|
-
|
|
131
|
+
You can optionally configure deduplication:
|
|
58
132
|
|
|
59
|
-
|
|
133
|
+
```ts
|
|
134
|
+
await client.store({
|
|
135
|
+
id: "user_123",
|
|
136
|
+
content: "The user uses Bun and TypeScript.",
|
|
137
|
+
dedupeThreshold: 0.9,
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`dedupeThreshold` controls how similar an existing memory can be before Lumi0 considers the new memory a duplicate.
|
|
142
|
+
|
|
143
|
+
### `batch()`
|
|
144
|
+
|
|
145
|
+
Stores multiple memories in a single request.
|
|
60
146
|
|
|
61
147
|
```ts
|
|
62
148
|
await client.batch([
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
149
|
+
{
|
|
150
|
+
id: "user_123",
|
|
151
|
+
content: "The user works with Hono.",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: "user_123",
|
|
155
|
+
content: "The user prefers practical implementation details.",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: "user_123",
|
|
159
|
+
content: "The user uses Bun for backend services.",
|
|
160
|
+
},
|
|
71
161
|
]);
|
|
72
162
|
```
|
|
73
163
|
|
|
74
|
-
|
|
164
|
+
Batching is useful when your application needs to save multiple pieces of context at once.
|
|
75
165
|
|
|
76
|
-
|
|
166
|
+
For example, after a conversation:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
await client.batch([
|
|
170
|
+
{
|
|
171
|
+
id: "user_123",
|
|
172
|
+
content: "The user is building an AI application.",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: "user_123",
|
|
176
|
+
content: "The user prefers TypeScript.",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "user_123",
|
|
180
|
+
content: "The user uses Bun for backend development.",
|
|
181
|
+
},
|
|
182
|
+
]);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### `search()`
|
|
186
|
+
|
|
187
|
+
Searches stored memories semantically.
|
|
77
188
|
|
|
78
189
|
```ts
|
|
79
190
|
const memories = await client.search({
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
191
|
+
id: "user_123",
|
|
192
|
+
query: "Which backend framework does the user use?",
|
|
193
|
+
limit: 10,
|
|
194
|
+
minSimilarity: 0.7,
|
|
195
|
+
memoryType: "semantic",
|
|
85
196
|
});
|
|
86
197
|
```
|
|
87
198
|
|
|
88
|
-
|
|
199
|
+
You can use `limit` to control the maximum number of memories returned.
|
|
200
|
+
|
|
201
|
+
`minSimilarity` can be used to filter out results below a similarity threshold.
|
|
89
202
|
|
|
90
|
-
|
|
203
|
+
You can also specify a memory type:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
const memories = await client.search({
|
|
207
|
+
id: "user_123",
|
|
208
|
+
query: "What does the user know about this project?",
|
|
209
|
+
memoryType: "semantic",
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### `get()`
|
|
214
|
+
|
|
215
|
+
Retrieves a memory by its identifier.
|
|
91
216
|
|
|
92
217
|
```ts
|
|
93
218
|
const memory = await client.get({
|
|
94
|
-
|
|
95
|
-
version: 2,
|
|
219
|
+
id: "memory_123",
|
|
96
220
|
});
|
|
97
221
|
```
|
|
98
222
|
|
|
99
|
-
|
|
223
|
+
To retrieve a specific version:
|
|
100
224
|
|
|
101
|
-
|
|
225
|
+
```ts
|
|
226
|
+
const memory = await client.get({
|
|
227
|
+
id: "memory_123",
|
|
228
|
+
version: 2,
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
This is useful when your application needs to inspect a particular historical version of a memory.
|
|
233
|
+
|
|
234
|
+
### `forget()`
|
|
235
|
+
|
|
236
|
+
Deletes a stored memory.
|
|
102
237
|
|
|
103
238
|
```ts
|
|
104
239
|
await client.forget({
|
|
105
|
-
|
|
240
|
+
id: "memory_123",
|
|
106
241
|
});
|
|
107
242
|
```
|
|
108
243
|
|
|
109
|
-
### `
|
|
244
|
+
### `files()`
|
|
245
|
+
|
|
246
|
+
Uploads and ingests a document from a URL.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const upload = await client.files({
|
|
250
|
+
url: "https://example.com/document.pdf",
|
|
251
|
+
id: "tenant_123",
|
|
252
|
+
});
|
|
253
|
+
```
|
|
110
254
|
|
|
111
|
-
|
|
255
|
+
The `id` can be either a Lumi0 tenant ID or an external ID from your application.
|
|
256
|
+
|
|
257
|
+
Lumi0 determines the document type from the URL and supports the following file extensions:
|
|
258
|
+
|
|
259
|
+
| Extension | MIME type |
|
|
260
|
+
| --------- | --------------------------------------------------------------------------- |
|
|
261
|
+
| `.csv` | `text/csv` |
|
|
262
|
+
| `.docx` | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |
|
|
263
|
+
| `.eml` | `message/rfc822` |
|
|
264
|
+
| `.htm` | `text/html` |
|
|
265
|
+
| `.html` | `text/html` |
|
|
266
|
+
| `.json` | `application/json` |
|
|
267
|
+
| `.jsonl` | `application/x-ndjson` |
|
|
268
|
+
| `.md` | `text/markdown` |
|
|
269
|
+
| `.mdx` | `text/markdown` |
|
|
270
|
+
| `.mbox` | `application/mbox` |
|
|
271
|
+
| `.pdf` | `application/pdf` |
|
|
272
|
+
| `.pptx` | `application/vnd.openxmlformats-officedocument.presentationml.presentation` |
|
|
273
|
+
| `.tsv` | `text/tab-separated-values` |
|
|
274
|
+
| `.txt` | `text/plain` |
|
|
275
|
+
| `.xls` | `application/vnd.ms-excel` |
|
|
276
|
+
| `.xlsx` | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
|
|
277
|
+
| `.xml` | `application/xml` |
|
|
278
|
+
| `.yaml` | `application/yaml` |
|
|
279
|
+
| `.yml` | `application/yaml` |
|
|
280
|
+
|
|
281
|
+
Example:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const upload = await client.files({
|
|
285
|
+
url: "https://example.com/company-handbook.pdf",
|
|
286
|
+
id: "customer_123",
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log(upload);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
This allows applications to ingest documents without first downloading and uploading the file themselves.
|
|
293
|
+
|
|
294
|
+
### `compress()`
|
|
295
|
+
|
|
296
|
+
Compresses context while attempting to retain information that is relevant to a query.
|
|
297
|
+
|
|
298
|
+
This is useful before sending large context windows to an LLM.
|
|
112
299
|
|
|
113
300
|
```ts
|
|
114
301
|
const result = await client.compress({
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
302
|
+
content: JSON.stringify(memories),
|
|
303
|
+
query: "What is the user's preferred backend stack?",
|
|
304
|
+
mode: "adaptive",
|
|
305
|
+
budgetRatio: 0.5,
|
|
119
306
|
});
|
|
120
307
|
|
|
121
308
|
console.log(result.data.compressedText);
|
|
122
309
|
console.log(`${result.data.tokensSaved} tokens saved`);
|
|
123
310
|
```
|
|
124
311
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
312
|
+
The returned data can be used as the context for your LLM request:
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
const result = await client.compress({
|
|
316
|
+
content: JSON.stringify(memories),
|
|
317
|
+
query: "What is the user's preferred backend stack?",
|
|
318
|
+
mode: "adaptive",
|
|
319
|
+
budgetRatio: 0.5,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const context = result.data.compressedText;
|
|
323
|
+
|
|
324
|
+
// Pass `context` to your LLM.
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Compression modes
|
|
328
|
+
|
|
329
|
+
Lumi0 supports two compression modes.
|
|
330
|
+
|
|
331
|
+
**Adaptive**
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
await client.compress({
|
|
335
|
+
content,
|
|
336
|
+
query,
|
|
337
|
+
mode: "adaptive",
|
|
338
|
+
budgetRatio: 0.5,
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Adaptive compression allows Lumi0 to determine how much context should be retained based on the query and content.
|
|
343
|
+
|
|
344
|
+
**Fixed**
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
await client.compress({
|
|
348
|
+
content,
|
|
349
|
+
query,
|
|
350
|
+
mode: "fixed",
|
|
351
|
+
budgetRatio: 0.5,
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Fixed compression uses `budgetRatio` to target a specific retained-context ratio.
|
|
356
|
+
|
|
357
|
+
For example, a `budgetRatio` of `0.5` targets approximately half of the original context budget.
|
|
358
|
+
|
|
359
|
+
## Building an AI Memory Loop
|
|
360
|
+
|
|
361
|
+
A typical application can combine `store()` and `search()`:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
import { Lumi0 } from "@lumi0/sdk";
|
|
365
|
+
|
|
366
|
+
const client = new Lumi0({
|
|
367
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// Save information learned from the conversation.
|
|
371
|
+
await client.store({
|
|
372
|
+
id: "user_123",
|
|
373
|
+
content: "The user prefers concise answers.",
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
// Retrieve relevant memories before generating a response.
|
|
377
|
+
const memories = await client.search({
|
|
378
|
+
id: "user_123",
|
|
379
|
+
query: "How should I respond to this user?",
|
|
380
|
+
limit: 5,
|
|
381
|
+
});
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
You can then inject the retrieved memories into your LLM context.
|
|
385
|
+
|
|
386
|
+
## File Ingestion + Memory
|
|
387
|
+
|
|
388
|
+
Lumi0 can combine external documents with persistent memory.
|
|
389
|
+
|
|
390
|
+
For example, an application can ingest a document for a tenant and later use the resulting knowledge alongside stored memories:
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
const upload = await client.files({
|
|
394
|
+
url: "https://example.com/product-documentation.pdf",
|
|
395
|
+
id: "tenant_123",
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
await client.store({
|
|
399
|
+
id: "tenant_123",
|
|
400
|
+
content: "The customer is building an AI support application.",
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
This provides a simple pipeline for applications that need both user-specific memory and external document knowledge.
|
|
405
|
+
|
|
406
|
+
## Memory + Compression
|
|
407
|
+
|
|
408
|
+
For applications with large memory collections, you can combine semantic retrieval with compression:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
const memories = await client.search({
|
|
412
|
+
id: "user_123",
|
|
413
|
+
query: "What does the user prefer when writing code?",
|
|
414
|
+
limit: 20,
|
|
415
|
+
minSimilarity: 0.7,
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const compressed = await client.compress({
|
|
419
|
+
content: JSON.stringify(memories),
|
|
420
|
+
query: "What does the user prefer when writing code?",
|
|
421
|
+
mode: "adaptive",
|
|
422
|
+
budgetRatio: 0.5,
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const context = compressed.data.compressedText;
|
|
426
|
+
|
|
427
|
+
console.log(context);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
This creates a pipeline:
|
|
431
|
+
|
|
432
|
+
```text
|
|
433
|
+
Stored Memories
|
|
434
|
+
↓
|
|
435
|
+
Semantic Search
|
|
436
|
+
↓
|
|
437
|
+
Relevant Memories
|
|
438
|
+
↓
|
|
439
|
+
Context Compression
|
|
440
|
+
↓
|
|
441
|
+
Compressed Context
|
|
442
|
+
↓
|
|
443
|
+
LLM
|
|
444
|
+
```
|
|
128
445
|
|
|
129
446
|
## Configuration
|
|
130
447
|
|
|
448
|
+
The client accepts configuration options:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
const client = new Lumi0({
|
|
452
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
453
|
+
baseUrl: "https://api.lumi0.com/api/v1",
|
|
454
|
+
timeout: 30_000,
|
|
455
|
+
});
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### `apiKey`
|
|
459
|
+
|
|
460
|
+
Your Lumi0 API key.
|
|
461
|
+
|
|
462
|
+
```ts
|
|
463
|
+
apiKey: process.env.LUMI0_API_KEY!
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### `baseUrl`
|
|
467
|
+
|
|
468
|
+
The Lumi0 API endpoint.
|
|
469
|
+
|
|
470
|
+
Default:
|
|
471
|
+
|
|
472
|
+
```text
|
|
473
|
+
https://api.lumi0.com/api/v1
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
You can override it:
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
const client = new Lumi0({
|
|
480
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
481
|
+
baseUrl: "https://api.lumi0.com/api/v1",
|
|
482
|
+
});
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
This can be useful when working with a different API environment.
|
|
486
|
+
|
|
487
|
+
### `timeout`
|
|
488
|
+
|
|
489
|
+
Maximum time, in milliseconds, that the SDK waits for an HTTP request.
|
|
490
|
+
|
|
491
|
+
Default:
|
|
492
|
+
|
|
493
|
+
```ts
|
|
494
|
+
30_000
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Example:
|
|
498
|
+
|
|
131
499
|
```ts
|
|
132
500
|
const client = new Lumi0({
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
timeout: 30_000,
|
|
501
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
502
|
+
timeout: 60_000,
|
|
136
503
|
});
|
|
137
504
|
```
|
|
138
505
|
|
|
139
|
-
|
|
140
|
-
|
|
506
|
+
## Environment Variables
|
|
507
|
+
|
|
508
|
+
A typical `.env` file:
|
|
509
|
+
|
|
510
|
+
```env
|
|
511
|
+
LUMI0_API_KEY=your_api_key
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
Then:
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
import { Lumi0 } from "@lumi0/sdk";
|
|
518
|
+
|
|
519
|
+
const client = new Lumi0({
|
|
520
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
Do not commit your `.env` file or API keys to source control.
|
|
525
|
+
|
|
526
|
+
## Error Handling
|
|
527
|
+
|
|
528
|
+
SDK requests reject with an `Error` when Lumi0 returns a non-success HTTP status.
|
|
529
|
+
|
|
530
|
+
Use `try/catch` around SDK operations:
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
try {
|
|
534
|
+
const memories = await client.search({
|
|
535
|
+
id: "user_123",
|
|
536
|
+
query: "What does the user prefer?",
|
|
537
|
+
limit: 5,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
console.log(memories);
|
|
541
|
+
} catch (error) {
|
|
542
|
+
console.error("Lumi0 request failed:", error);
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
The error message includes the HTTP status and the API-provided error message when available.
|
|
547
|
+
|
|
548
|
+
For production applications, handle failures explicitly rather than assuming every operation succeeds.
|
|
549
|
+
|
|
550
|
+
## Server-Side Usage
|
|
551
|
+
|
|
552
|
+
The Lumi0 API key should be kept private.
|
|
553
|
+
|
|
554
|
+
Recommended:
|
|
555
|
+
|
|
556
|
+
```ts
|
|
557
|
+
// Server-side code
|
|
558
|
+
const client = new Lumi0({
|
|
559
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
560
|
+
});
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Avoid putting your API key directly into client-side applications:
|
|
564
|
+
|
|
565
|
+
```ts
|
|
566
|
+
// Don't expose your secret API key in browser code.
|
|
567
|
+
const client = new Lumi0({
|
|
568
|
+
apiKey: "your-secret-api-key",
|
|
569
|
+
});
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
For a Next.js application, use Lumi0 from server-side code such as API routes, Route Handlers, Server Actions, or your backend.
|
|
573
|
+
|
|
574
|
+
## Example: User Memory
|
|
575
|
+
|
|
576
|
+
A simple chat application can save user preferences:
|
|
577
|
+
|
|
578
|
+
```ts
|
|
579
|
+
await client.store({
|
|
580
|
+
id: "user_123",
|
|
581
|
+
content: "The user prefers concise responses.",
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
await client.store({
|
|
585
|
+
id: "user_123",
|
|
586
|
+
content: "The user prefers TypeScript examples.",
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
await client.store({
|
|
590
|
+
id: "user_123",
|
|
591
|
+
content: "The user uses Bun.",
|
|
592
|
+
});
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Later, retrieve the relevant information:
|
|
596
|
+
|
|
597
|
+
```ts
|
|
598
|
+
const memories = await client.search({
|
|
599
|
+
id: "user_123",
|
|
600
|
+
query: "What should I know about this user's coding preferences?",
|
|
601
|
+
limit: 10,
|
|
602
|
+
});
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## Example: Conversation Memory
|
|
606
|
+
|
|
607
|
+
You can store useful information extracted from a conversation:
|
|
608
|
+
|
|
609
|
+
```ts
|
|
610
|
+
await client.batch([
|
|
611
|
+
{
|
|
612
|
+
id: "user_123",
|
|
613
|
+
content: "The user is building a SaaS application.",
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
id: "user_123",
|
|
617
|
+
content: "The user uses TypeScript for backend development.",
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
id: "user_123",
|
|
621
|
+
content: "The user prefers concise technical explanations.",
|
|
622
|
+
},
|
|
623
|
+
]);
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Then retrieve only the information relevant to a new request:
|
|
627
|
+
|
|
628
|
+
```ts
|
|
629
|
+
const memories = await client.search({
|
|
630
|
+
id: "user_123",
|
|
631
|
+
query: "What technical preferences should I consider?",
|
|
632
|
+
limit: 5,
|
|
633
|
+
});
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
## TypeScript
|
|
637
|
+
|
|
638
|
+
The SDK is designed for TypeScript applications and provides typed method interfaces.
|
|
639
|
+
|
|
640
|
+
```ts
|
|
641
|
+
import { Lumi0 } from "@lumi0/sdk";
|
|
642
|
+
|
|
643
|
+
const client = new Lumi0({
|
|
644
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
const result = await client.search({
|
|
648
|
+
id: "user_123",
|
|
649
|
+
query: "What does the user prefer?",
|
|
650
|
+
limit: 5,
|
|
651
|
+
});
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Your editor can provide autocomplete and type checking for Lumi0 client methods and their options.
|
|
655
|
+
|
|
656
|
+
## Runtime Support
|
|
657
|
+
|
|
658
|
+
The SDK is designed to work with modern JavaScript runtimes, including:
|
|
659
|
+
|
|
660
|
+
* Bun
|
|
661
|
+
* Node.js
|
|
662
|
+
|
|
663
|
+
Bun installation:
|
|
664
|
+
|
|
665
|
+
```bash
|
|
666
|
+
bun add @lumi0/sdk
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
npm installation:
|
|
670
|
+
|
|
671
|
+
```bash
|
|
672
|
+
npm install @lumi0/sdk
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
## API Summary
|
|
676
|
+
|
|
677
|
+
| Method | Purpose |
|
|
678
|
+
| ------------ | --------------------------------------- |
|
|
679
|
+
| `store()` | Store one memory |
|
|
680
|
+
| `batch()` | Store multiple memories |
|
|
681
|
+
| `search()` | Semantically search memories |
|
|
682
|
+
| `get()` | Retrieve a memory or specific version |
|
|
683
|
+
| `forget()` | Delete a memory |
|
|
684
|
+
| `files()` | Upload and ingest a document from a URL |
|
|
685
|
+
| `compress()` | Compress context relevant to a query |
|
|
686
|
+
|
|
687
|
+
## Complete Example
|
|
688
|
+
|
|
689
|
+
```ts
|
|
690
|
+
import { Lumi0 } from "@lumi0/sdk";
|
|
691
|
+
|
|
692
|
+
const client = new Lumi0({
|
|
693
|
+
apiKey: process.env.LUMI0_API_KEY!,
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
async function main() {
|
|
697
|
+
// Upload a document.
|
|
698
|
+
const upload = await client.files({
|
|
699
|
+
url: "https://example.com/document.pdf",
|
|
700
|
+
id: "tenant_123",
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
console.log(upload);
|
|
704
|
+
|
|
705
|
+
// Store memories.
|
|
706
|
+
await client.batch([
|
|
707
|
+
{
|
|
708
|
+
id: "user_123",
|
|
709
|
+
content: "The user prefers concise TypeScript examples.",
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: "user_123",
|
|
713
|
+
content: "The user uses Bun for backend development.",
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
id: "user_123",
|
|
717
|
+
content: "The user works with Hono.",
|
|
718
|
+
},
|
|
719
|
+
]);
|
|
720
|
+
|
|
721
|
+
// Search relevant memories.
|
|
722
|
+
const memories = await client.search({
|
|
723
|
+
id: "user_123",
|
|
724
|
+
query: "What backend technologies does the user use?",
|
|
725
|
+
limit: 10,
|
|
726
|
+
minSimilarity: 0.7,
|
|
727
|
+
memoryType: "semantic",
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// Compress retrieved context.
|
|
731
|
+
const compressed = await client.compress({
|
|
732
|
+
content: JSON.stringify(memories),
|
|
733
|
+
query: "What backend technologies does the user use?",
|
|
734
|
+
mode: "adaptive",
|
|
735
|
+
budgetRatio: 0.5,
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
console.log(compressed.data.compressedText);
|
|
739
|
+
console.log(`${compressed.data.tokensSaved} tokens saved`);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
main().catch(console.error);
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
## Links
|
|
746
|
+
|
|
747
|
+
* Website: https://lumi0.com
|
|
748
|
+
* API: https://api.lumi0.com
|
|
749
|
+
* npm: https://www.npmjs.com/package/@lumi0/sdk
|
|
141
750
|
|
|
142
|
-
##
|
|
751
|
+
## License
|
|
143
752
|
|
|
144
|
-
|
|
145
|
-
The error message includes the HTTP status and the API-provided error message
|
|
146
|
-
when available.
|
|
753
|
+
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,43 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
+
interface HttpClientOptions {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
headers?: globalThis.HeadersInit;
|
|
7
|
+
}
|
|
8
|
+
interface ErrorResponse {
|
|
9
|
+
message?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
2
12
|
type Lumi0Options = {
|
|
3
13
|
apiKey: string;
|
|
4
14
|
baseUrl?: string;
|
|
5
15
|
timeout?: number;
|
|
6
16
|
};
|
|
17
|
+
type PostBody = Record<string, unknown>;
|
|
18
|
+
interface IPostBody {
|
|
19
|
+
userId: string;
|
|
20
|
+
collectionId: string;
|
|
21
|
+
}
|
|
7
22
|
interface StoreMemoryInput {
|
|
8
23
|
content: string;
|
|
9
24
|
dedupeThreshold?: number;
|
|
10
25
|
id: string;
|
|
11
26
|
}
|
|
27
|
+
interface BuildContextInput {
|
|
28
|
+
id: string;
|
|
29
|
+
query: string;
|
|
30
|
+
limit?: number;
|
|
31
|
+
minSimilarity?: number;
|
|
32
|
+
}
|
|
33
|
+
interface UploadFileInput {
|
|
34
|
+
id: string;
|
|
35
|
+
url: string;
|
|
36
|
+
}
|
|
37
|
+
interface MemoryRollbackInput {
|
|
38
|
+
memoryId: string;
|
|
39
|
+
version: number;
|
|
40
|
+
}
|
|
12
41
|
interface SearchMemoryInput {
|
|
13
42
|
query: string;
|
|
14
43
|
limit?: number;
|
|
@@ -26,7 +55,24 @@ interface CompressMemoryInput {
|
|
|
26
55
|
budgetRatio?: number;
|
|
27
56
|
mode: "fixed" | "adaptive";
|
|
28
57
|
}
|
|
29
|
-
interface
|
|
58
|
+
interface MemoryVersion {
|
|
59
|
+
id: string;
|
|
60
|
+
memoryId: string;
|
|
61
|
+
version: number;
|
|
62
|
+
action: "created" | "updated" | "deleted";
|
|
63
|
+
content: string;
|
|
64
|
+
metadata: {
|
|
65
|
+
tags: string[];
|
|
66
|
+
summary: string;
|
|
67
|
+
category: string;
|
|
68
|
+
externalId: string;
|
|
69
|
+
importance: number;
|
|
70
|
+
memoryType: "semantic" | "episodic" | "procedural";
|
|
71
|
+
};
|
|
72
|
+
createdBy: string;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
}
|
|
75
|
+
interface Compress {
|
|
30
76
|
compressedText: string;
|
|
31
77
|
originalTokens: number;
|
|
32
78
|
keptTokens: number;
|
|
@@ -37,24 +83,62 @@ interface CompressMemoryResult {
|
|
|
37
83
|
policyName: string;
|
|
38
84
|
keptLineRatio: number;
|
|
39
85
|
}
|
|
40
|
-
interface CompressMemoryApiResponse {
|
|
41
|
-
success: boolean;
|
|
42
|
-
data: CompressMemoryResult;
|
|
43
|
-
}
|
|
44
86
|
interface ForgetMemoryInput {
|
|
45
87
|
id: string;
|
|
46
88
|
}
|
|
89
|
+
interface Context {
|
|
90
|
+
data: string;
|
|
91
|
+
}
|
|
92
|
+
interface Search {
|
|
93
|
+
id: string;
|
|
94
|
+
collectionId: string;
|
|
95
|
+
externalId: string;
|
|
96
|
+
content: string;
|
|
97
|
+
memoryType: string;
|
|
98
|
+
importance: number;
|
|
99
|
+
category: string;
|
|
100
|
+
summary: string;
|
|
101
|
+
tags: string[];
|
|
102
|
+
version: number;
|
|
103
|
+
createdAt: Date;
|
|
104
|
+
updatedAt: Date;
|
|
105
|
+
similarity: number;
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/http.d.ts
|
|
109
|
+
declare class HttpClient {
|
|
110
|
+
private readonly options;
|
|
111
|
+
constructor(options: HttpClientOptions);
|
|
112
|
+
request<T>(path: string, init?: RequestInit): Promise<T>;
|
|
113
|
+
get<T>(path: string): Promise<T>;
|
|
114
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
115
|
+
put<T>(path: string, body?: unknown): Promise<T>;
|
|
116
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
117
|
+
delete<T>(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<T>;
|
|
118
|
+
private parseError;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/memory.d.ts
|
|
122
|
+
declare class MemoryApi {
|
|
123
|
+
private readonly http;
|
|
124
|
+
constructor(http: HttpClient);
|
|
125
|
+
history(id: string): Promise<MemoryVersion[]>;
|
|
126
|
+
rollback(input: MemoryRollbackInput): Promise<unknown>;
|
|
127
|
+
}
|
|
47
128
|
//#endregion
|
|
48
129
|
//#region src/client.d.ts
|
|
49
130
|
declare class Lumi0 {
|
|
50
131
|
private readonly http;
|
|
132
|
+
readonly mem: MemoryApi;
|
|
51
133
|
constructor(option: Lumi0Options);
|
|
52
134
|
store(input: StoreMemoryInput): Promise<unknown>;
|
|
53
|
-
search(input: SearchMemoryInput): Promise<
|
|
54
|
-
get(input: GetMemoryInput): Promise<
|
|
135
|
+
search(input: SearchMemoryInput): Promise<Search>;
|
|
136
|
+
get(input: GetMemoryInput): Promise<Search>;
|
|
55
137
|
forget(input: ForgetMemoryInput): Promise<unknown>;
|
|
56
138
|
batch(input: StoreMemoryInput[]): Promise<unknown>;
|
|
57
|
-
|
|
139
|
+
context(input: BuildContextInput): Promise<Context>;
|
|
140
|
+
files(input: UploadFileInput): Promise<unknown>;
|
|
141
|
+
compress(input: CompressMemoryInput): Promise<Compress>;
|
|
58
142
|
}
|
|
59
143
|
//#endregion
|
|
60
|
-
export { Lumi0 };
|
|
144
|
+
export { BuildContextInput, Compress, CompressMemoryInput, Context, ErrorResponse, ForgetMemoryInput, GetMemoryInput, HttpClientOptions, IPostBody, Lumi0, Lumi0Options, MemoryRollbackInput, MemoryVersion, PostBody, Search, SearchMemoryInput, StoreMemoryInput, UploadFileInput };
|
package/dist/index.mjs
CHANGED
|
@@ -36,12 +36,6 @@ var HttpClient = class {
|
|
|
36
36
|
body: body ? JSON.stringify(body) : void 0
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
-
list(path, items) {
|
|
40
|
-
return this.request(path, {
|
|
41
|
-
method: "POST",
|
|
42
|
-
body: JSON.stringify(items)
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
39
|
put(path, body) {
|
|
46
40
|
return this.request(path, {
|
|
47
41
|
method: "PUT",
|
|
@@ -72,9 +66,24 @@ var HttpClient = class {
|
|
|
72
66
|
}
|
|
73
67
|
};
|
|
74
68
|
//#endregion
|
|
69
|
+
//#region src/memory.ts
|
|
70
|
+
var MemoryApi = class {
|
|
71
|
+
http;
|
|
72
|
+
constructor(http) {
|
|
73
|
+
this.http = http;
|
|
74
|
+
}
|
|
75
|
+
history(id) {
|
|
76
|
+
return this.http.get(`/memories/history/${id}`).then((response) => response.data);
|
|
77
|
+
}
|
|
78
|
+
rollback(input) {
|
|
79
|
+
return this.http.post(`/memories/${input.memoryId}/versions/${input.version}/rollback`);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
75
83
|
//#region src/client.ts
|
|
76
84
|
var Lumi0 = class {
|
|
77
85
|
http;
|
|
86
|
+
mem;
|
|
78
87
|
constructor(option) {
|
|
79
88
|
const apiKey = option.apiKey;
|
|
80
89
|
this.http = new HttpClient({
|
|
@@ -82,6 +91,7 @@ var Lumi0 = class {
|
|
|
82
91
|
apiKey,
|
|
83
92
|
timeout: option.timeout ?? 3e4
|
|
84
93
|
});
|
|
94
|
+
this.mem = new MemoryApi(this.http);
|
|
85
95
|
}
|
|
86
96
|
store(input) {
|
|
87
97
|
return this.http.post("/memory", {
|
|
@@ -93,10 +103,10 @@ var Lumi0 = class {
|
|
|
93
103
|
return this.http.post("/memory/search", {
|
|
94
104
|
...input,
|
|
95
105
|
externalId: input.id
|
|
96
|
-
});
|
|
106
|
+
}).then((res) => res.data);
|
|
97
107
|
}
|
|
98
108
|
get(input) {
|
|
99
|
-
return this.http.post("/memory/get", input);
|
|
109
|
+
return this.http.post("/memory/get", input).then((res) => res.data);
|
|
100
110
|
}
|
|
101
111
|
forget(input) {
|
|
102
112
|
return this.http.delete(`/memory/${input.id}`);
|
|
@@ -104,8 +114,20 @@ var Lumi0 = class {
|
|
|
104
114
|
batch(input) {
|
|
105
115
|
return this.http.post("/memory/batch", input.map((item) => ({ ...item })));
|
|
106
116
|
}
|
|
117
|
+
context(input) {
|
|
118
|
+
return this.http.post("/memory/context", {
|
|
119
|
+
...input,
|
|
120
|
+
externalId: input.id
|
|
121
|
+
}).then((res) => res.data);
|
|
122
|
+
}
|
|
123
|
+
files(input) {
|
|
124
|
+
return this.http.post("/memory/batch", {
|
|
125
|
+
...input,
|
|
126
|
+
externalId: input.id
|
|
127
|
+
});
|
|
128
|
+
}
|
|
107
129
|
compress(input) {
|
|
108
|
-
return this.http.post("/compress", input);
|
|
130
|
+
return this.http.post("/compress", input).then((res) => res.data);
|
|
109
131
|
}
|
|
110
132
|
};
|
|
111
133
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumi0/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Official TypeScript SDK for Lumi0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
7
9
|
"repository": {
|
|
8
10
|
"type": "git",
|
|
9
11
|
"url": "https://github.com/lumi0ai/lumi0-ts.git"
|