@olane/o-storage 0.7.2 → 0.7.4
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 +1008 -0
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -0,0 +1,1008 @@
|
|
|
1
|
+
# o-storage
|
|
2
|
+
|
|
3
|
+
A unified storage application for Olane OS that provides multiple storage backends with a consistent interface.
|
|
4
|
+
|
|
5
|
+
**TL;DR**: Store, retrieve, and manage data across memory, disk, secure encrypted storage, and AI-powered placeholder storage using a simple key-value interface with `o://` addresses.
|
|
6
|
+
|
|
7
|
+
## Quick Start {#quick-start}
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install
|
|
11
|
+
npm install @olane/o-storage
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Basic usage with disk storage
|
|
16
|
+
import { StorageTool } from '@olane/o-storage';
|
|
17
|
+
import { oAddress } from '@olane/o-core';
|
|
18
|
+
|
|
19
|
+
// Initialize storage application
|
|
20
|
+
const storage = new StorageTool({
|
|
21
|
+
parent: null,
|
|
22
|
+
leader: leaderAddress
|
|
23
|
+
});
|
|
24
|
+
await storage.start();
|
|
25
|
+
|
|
26
|
+
// Store data
|
|
27
|
+
await leader.use(new oAddress('o://disk'), {
|
|
28
|
+
method: 'put',
|
|
29
|
+
params: {
|
|
30
|
+
key: 'user-config',
|
|
31
|
+
value: JSON.stringify({ theme: 'dark', lang: 'en' })
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Retrieve data
|
|
36
|
+
const result = await leader.use(new oAddress('o://disk/user-config'));
|
|
37
|
+
console.log(result.result.data);
|
|
38
|
+
// { value: '{"theme":"dark","lang":"en"}' }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Overview {#overview}
|
|
42
|
+
|
|
43
|
+
`o-storage` is a **Level 3 Application** (multiple coordinated nodes) that provides a unified storage layer for Olane OS. It includes four specialized storage providers, each optimized for different use cases.
|
|
44
|
+
|
|
45
|
+
### What it does
|
|
46
|
+
|
|
47
|
+
- **Stores data** with multiple backend options (memory, disk, encrypted, AI-powered)
|
|
48
|
+
- **Retrieves data** using `o://` addresses or explicit method calls
|
|
49
|
+
- **Manages data** with put, get, delete, and has operations
|
|
50
|
+
- **Intelligently summarizes** large documents with placeholder storage
|
|
51
|
+
- **Routes requests** automatically to the appropriate storage provider
|
|
52
|
+
|
|
53
|
+
### Architecture
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌─────────────────────────────────────────────────────────┐
|
|
57
|
+
│ StorageTool (Application) │
|
|
58
|
+
│ o://storage │
|
|
59
|
+
│ • Routes requests to providers │
|
|
60
|
+
└─────────────────────────────────────────────────────────┘
|
|
61
|
+
⬇ manages
|
|
62
|
+
┌──────────────┬──────────────┬──────────────┬──────────────┐
|
|
63
|
+
⬇ ⬇ ⬇ ⬇ ⬇
|
|
64
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐
|
|
65
|
+
│ Memory │ │ Disk │ │ Secure │ │ Placeholder │
|
|
66
|
+
│ o://mem │ │ o://disk │ │ o://sec │ │ o://placehldr│
|
|
67
|
+
│ Fast │ │ Persist │ │ Encrypt │ │ AI-Powered │
|
|
68
|
+
└──────────┘ └──────────┘ └──────────┘ └──────────────┘
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Storage Providers {#storage-providers}
|
|
72
|
+
|
|
73
|
+
### Memory Storage (`o://memory`) {#memory-storage}
|
|
74
|
+
|
|
75
|
+
Fast, volatile storage for temporary data.
|
|
76
|
+
|
|
77
|
+
**Best for**: Caching, session data, temporary computations
|
|
78
|
+
|
|
79
|
+
**Characteristics**:
|
|
80
|
+
- ⚡ Fastest performance
|
|
81
|
+
- 💾 Lost on restart
|
|
82
|
+
- 🔓 No encryption
|
|
83
|
+
- 🎯 Simple key-value storage
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Store in memory
|
|
87
|
+
await leader.use(new oAddress('o://memory'), {
|
|
88
|
+
method: 'put',
|
|
89
|
+
params: {
|
|
90
|
+
key: 'session-token',
|
|
91
|
+
value: 'abc123xyz'
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Retrieve from memory
|
|
96
|
+
const result = await leader.use(new oAddress('o://memory/session-token'));
|
|
97
|
+
console.log(result.result.data.value); // 'abc123xyz'
|
|
98
|
+
|
|
99
|
+
// Check if exists
|
|
100
|
+
const exists = await leader.use(new oAddress('o://memory'), {
|
|
101
|
+
method: 'has',
|
|
102
|
+
params: { key: 'session-token' }
|
|
103
|
+
});
|
|
104
|
+
console.log(exists.result.data.success); // true
|
|
105
|
+
|
|
106
|
+
// Delete from memory
|
|
107
|
+
await leader.use(new oAddress('o://memory'), {
|
|
108
|
+
method: 'delete',
|
|
109
|
+
params: { key: 'session-token' }
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### Disk Storage (`o://disk`) {#disk-storage}
|
|
116
|
+
|
|
117
|
+
Persistent storage on the local filesystem.
|
|
118
|
+
|
|
119
|
+
**Best for**: Application state, configuration files, persistent data
|
|
120
|
+
|
|
121
|
+
**Characteristics**:
|
|
122
|
+
- 💾 Persists across restarts
|
|
123
|
+
- 📁 Stored in `~/.olane/storage/` by default
|
|
124
|
+
- 📝 JSON format with metadata
|
|
125
|
+
- 🔓 No encryption
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Store on disk
|
|
129
|
+
await leader.use(new oAddress('o://disk'), {
|
|
130
|
+
method: 'put',
|
|
131
|
+
params: {
|
|
132
|
+
key: 'app-settings',
|
|
133
|
+
value: JSON.stringify({
|
|
134
|
+
theme: 'dark',
|
|
135
|
+
notifications: true,
|
|
136
|
+
version: '1.0.0'
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Retrieve from disk
|
|
142
|
+
const result = await leader.use(new oAddress('o://disk/app-settings'));
|
|
143
|
+
const settings = JSON.parse(result.result.data.value);
|
|
144
|
+
console.log(settings);
|
|
145
|
+
// { theme: 'dark', notifications: true, version: '1.0.0' }
|
|
146
|
+
|
|
147
|
+
// Custom storage directory
|
|
148
|
+
const diskStorage = new DiskStorageProvider({
|
|
149
|
+
name: 'custom-disk',
|
|
150
|
+
leader: leaderAddress,
|
|
151
|
+
storageDir: '/custom/path/to/storage'
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### Secure Storage (`o://secure`) {#secure-storage}
|
|
158
|
+
|
|
159
|
+
Encrypted persistent storage using `o://encryption` service.
|
|
160
|
+
|
|
161
|
+
**Best for**: API keys, passwords, sensitive user data, credentials
|
|
162
|
+
|
|
163
|
+
**Characteristics**:
|
|
164
|
+
- 🔒 Encrypted at rest
|
|
165
|
+
- 💾 Persists across restarts
|
|
166
|
+
- 📁 Stored in `~/.olane/storage/`
|
|
167
|
+
- 🔐 Requires `o://encryption` node
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// Store encrypted data
|
|
171
|
+
await leader.use(new oAddress('o://secure'), {
|
|
172
|
+
method: 'put',
|
|
173
|
+
params: {
|
|
174
|
+
key: 'api-credentials',
|
|
175
|
+
value: JSON.stringify({
|
|
176
|
+
apiKey: 'sk_live_xxxxxxxxxxxxx',
|
|
177
|
+
apiSecret: 'secret_xxxxxxxxxxxxx'
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Retrieve and decrypt automatically
|
|
183
|
+
const result = await leader.use(new oAddress('o://secure/api-credentials'));
|
|
184
|
+
const credentials = JSON.parse(result.result.data.value);
|
|
185
|
+
console.log(credentials);
|
|
186
|
+
// { apiKey: 'sk_live_xxxxxxxxxxxxx', apiSecret: 'secret_xxxxxxxxxxxxx' }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Note**: Secure storage requires the `o://encryption` node to be running. The encryption/decryption happens automatically during put/get operations.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### Placeholder Storage (`o://placeholder`) {#placeholder-storage}
|
|
194
|
+
|
|
195
|
+
AI-powered storage that summarizes large documents to save context window space.
|
|
196
|
+
|
|
197
|
+
**Best for**: Large files, documents, code files that need summarization
|
|
198
|
+
|
|
199
|
+
**Characteristics**:
|
|
200
|
+
- 🤖 AI-powered summarization
|
|
201
|
+
- 💡 Intent-aware summaries
|
|
202
|
+
- 📝 Returns summary + original
|
|
203
|
+
- 🎯 Reduces context window usage
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// Store large document with intent
|
|
207
|
+
const largeDocument = `
|
|
208
|
+
[50,000 characters of code/documentation]
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
const result = await leader.use(new oAddress('o://placeholder'), {
|
|
212
|
+
method: 'put',
|
|
213
|
+
params: {
|
|
214
|
+
key: 'large-codebase',
|
|
215
|
+
value: largeDocument,
|
|
216
|
+
intent: 'Find all API endpoints and their authentication requirements'
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
console.log(result);
|
|
221
|
+
// {
|
|
222
|
+
// value: "[original 50,000 character document]",
|
|
223
|
+
// intent: "Find all API endpoints...",
|
|
224
|
+
// summary: "This is a Node.js Express application with 15 API endpoints...",
|
|
225
|
+
// instructions: "To save on context window size, I have summarized...",
|
|
226
|
+
// address: "o://placeholder/large-codebase"
|
|
227
|
+
// }
|
|
228
|
+
|
|
229
|
+
// Later, retrieve the original if needed
|
|
230
|
+
const original = await leader.use(
|
|
231
|
+
new oAddress('o://placeholder/large-codebase')
|
|
232
|
+
);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**How it works**:
|
|
236
|
+
|
|
237
|
+
1. **Store with intent**: Provide optional `intent` parameter describing what you need from the document
|
|
238
|
+
2. **AI summarizes**: Uses `o://intelligence` to create an intent-aligned summary
|
|
239
|
+
3. **Returns both**: Get original value + summary + instructions
|
|
240
|
+
4. **Reference address**: Use address in agents without re-uploading large content
|
|
241
|
+
|
|
242
|
+
**Use Case Example**:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// Agent needs to copy a large file
|
|
246
|
+
const fileContent = await fs.readFile('bigfile.txt', 'utf-8');
|
|
247
|
+
|
|
248
|
+
const stored = await leader.use(new oAddress('o://placeholder'), {
|
|
249
|
+
method: 'put',
|
|
250
|
+
params: {
|
|
251
|
+
key: 'source-file',
|
|
252
|
+
value: fileContent,
|
|
253
|
+
intent: 'Copy this file to a new location with a different name'
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Agent can now reference the summary instead of full content
|
|
258
|
+
// Summary: "This is a 50KB text file containing server configuration..."
|
|
259
|
+
// Agent knows it's a config file without loading all 50KB into context
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## API Reference {#api-reference}
|
|
263
|
+
|
|
264
|
+
### Storage Operations {#storage-operations}
|
|
265
|
+
|
|
266
|
+
All storage providers support these four core operations:
|
|
267
|
+
|
|
268
|
+
#### `put` {#put}
|
|
269
|
+
|
|
270
|
+
Store data under a key.
|
|
271
|
+
|
|
272
|
+
**Parameters**:
|
|
273
|
+
- `key` (string, required): Unique identifier for the data
|
|
274
|
+
- `value` (string, required): Data to store (serialize objects as JSON)
|
|
275
|
+
- `intent` (string, optional): Only for placeholder storage - describes what you need from the data
|
|
276
|
+
|
|
277
|
+
**Returns**:
|
|
278
|
+
```typescript
|
|
279
|
+
{
|
|
280
|
+
success: boolean;
|
|
281
|
+
error?: string; // Only present if success is false
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**Example**:
|
|
286
|
+
```typescript
|
|
287
|
+
const result = await leader.use(new oAddress('o://disk'), {
|
|
288
|
+
method: 'put',
|
|
289
|
+
params: {
|
|
290
|
+
key: 'user-123',
|
|
291
|
+
value: JSON.stringify({ name: 'Alice', email: 'alice@example.com' })
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
#### `get` {#get}
|
|
299
|
+
|
|
300
|
+
Retrieve data by key.
|
|
301
|
+
|
|
302
|
+
**Parameters**:
|
|
303
|
+
- `key` (string, required): Key to retrieve
|
|
304
|
+
|
|
305
|
+
**Returns**:
|
|
306
|
+
```typescript
|
|
307
|
+
{
|
|
308
|
+
value: string | null; // null if key doesn't exist
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Example**:
|
|
313
|
+
```typescript
|
|
314
|
+
// Method 1: Address with key
|
|
315
|
+
const result = await leader.use(new oAddress('o://disk/user-123'));
|
|
316
|
+
console.log(result.result.data.value);
|
|
317
|
+
|
|
318
|
+
// Method 2: Explicit get method
|
|
319
|
+
const result2 = await leader.use(new oAddress('o://disk'), {
|
|
320
|
+
method: 'get',
|
|
321
|
+
params: { key: 'user-123' }
|
|
322
|
+
});
|
|
323
|
+
console.log(result2.result.data.value);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
#### `delete` {#delete}
|
|
329
|
+
|
|
330
|
+
Remove data by key.
|
|
331
|
+
|
|
332
|
+
**Parameters**:
|
|
333
|
+
- `key` (string, required): Key to delete
|
|
334
|
+
|
|
335
|
+
**Returns**:
|
|
336
|
+
```typescript
|
|
337
|
+
{
|
|
338
|
+
success: boolean;
|
|
339
|
+
error?: string;
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Example**:
|
|
344
|
+
```typescript
|
|
345
|
+
await leader.use(new oAddress('o://memory'), {
|
|
346
|
+
method: 'delete',
|
|
347
|
+
params: { key: 'temporary-data' }
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
#### `has` {#has}
|
|
354
|
+
|
|
355
|
+
Check if a key exists.
|
|
356
|
+
|
|
357
|
+
**Parameters**:
|
|
358
|
+
- `key` (string, required): Key to check
|
|
359
|
+
|
|
360
|
+
**Returns**:
|
|
361
|
+
```typescript
|
|
362
|
+
{
|
|
363
|
+
success: boolean;
|
|
364
|
+
data?: boolean; // true if key exists, false otherwise
|
|
365
|
+
error?: string;
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Example**:
|
|
370
|
+
```typescript
|
|
371
|
+
const result = await leader.use(new oAddress('o://disk'), {
|
|
372
|
+
method: 'has',
|
|
373
|
+
params: { key: 'user-123' }
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
if (result.result.data.data) {
|
|
377
|
+
console.log('Key exists!');
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Storage Provider Classes {#storage-provider-classes}
|
|
382
|
+
|
|
383
|
+
### `StorageTool` {#storagetool}
|
|
384
|
+
|
|
385
|
+
Main application class that manages all storage providers.
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { StorageTool } from '@olane/o-storage';
|
|
389
|
+
|
|
390
|
+
const storage = new StorageTool({
|
|
391
|
+
parent: parentAddress,
|
|
392
|
+
leader: leaderAddress
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
await storage.start();
|
|
396
|
+
// Automatically initializes:
|
|
397
|
+
// - o://memory (MemoryStorageProvider)
|
|
398
|
+
// - o://disk (DiskStorageProvider)
|
|
399
|
+
// - o://secure (SecureStorageProvider)
|
|
400
|
+
// - o://placeholder (PlaceholderTool)
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
### `MemoryStorageProvider` {#memorystorageprovider}
|
|
406
|
+
|
|
407
|
+
In-memory storage provider.
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
import { MemoryStorageProvider } from '@olane/o-storage';
|
|
411
|
+
import { oAddress } from '@olane/o-core';
|
|
412
|
+
|
|
413
|
+
const memory = new MemoryStorageProvider({
|
|
414
|
+
name: 'custom-memory',
|
|
415
|
+
leader: leaderAddress,
|
|
416
|
+
address: new oAddress('o://custom-memory')
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
await memory.start();
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### `DiskStorageProvider` {#diskstorageprovider}
|
|
425
|
+
|
|
426
|
+
Filesystem-based storage provider.
|
|
427
|
+
|
|
428
|
+
**Configuration**:
|
|
429
|
+
```typescript
|
|
430
|
+
interface DiskStorageConfig {
|
|
431
|
+
name: string;
|
|
432
|
+
leader: oAddress;
|
|
433
|
+
address?: oAddress;
|
|
434
|
+
storageDir?: string; // Default: ~/.olane/storage
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Example**:
|
|
439
|
+
```typescript
|
|
440
|
+
import { DiskStorageProvider } from '@olane/o-storage';
|
|
441
|
+
|
|
442
|
+
const disk = new DiskStorageProvider({
|
|
443
|
+
name: 'my-disk',
|
|
444
|
+
leader: leaderAddress,
|
|
445
|
+
storageDir: '/path/to/custom/storage'
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
await disk.start();
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**File Format**:
|
|
452
|
+
```json
|
|
453
|
+
{
|
|
454
|
+
"value": "your-data-here",
|
|
455
|
+
"timestamp": "2024-10-06T12:00:00.000Z",
|
|
456
|
+
"key": "user-123"
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
### `SecureStorageProvider` {#securestorageprovider}
|
|
463
|
+
|
|
464
|
+
Encrypted disk storage provider (extends `DiskStorageProvider`).
|
|
465
|
+
|
|
466
|
+
**Requirements**:
|
|
467
|
+
- Requires `o://encryption` node to be running
|
|
468
|
+
- Uses same configuration as `DiskStorageProvider`
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { SecureStorageProvider } from '@olane/o-storage';
|
|
472
|
+
|
|
473
|
+
const secure = new SecureStorageProvider({
|
|
474
|
+
name: 'secure-vault',
|
|
475
|
+
leader: leaderAddress,
|
|
476
|
+
storageDir: '/secure/path'
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
await secure.start();
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
### `PlaceholderTool` {#placeholdertool}
|
|
485
|
+
|
|
486
|
+
AI-powered storage with summarization (extends `MemoryStorageProvider`).
|
|
487
|
+
|
|
488
|
+
**Requirements**:
|
|
489
|
+
- Requires `o://intelligence` node to be running
|
|
490
|
+
- Uses `o-lane` capability loop for AI processing
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
import { PlaceholderTool } from '@olane/o-storage';
|
|
494
|
+
|
|
495
|
+
const placeholder = new PlaceholderTool({
|
|
496
|
+
name: 'smart-storage',
|
|
497
|
+
leader: leaderAddress
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
await placeholder.start();
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
## Common Use Cases {#common-use-cases}
|
|
504
|
+
|
|
505
|
+
### Use Case 1: Configuration Management {#config-management}
|
|
506
|
+
|
|
507
|
+
Store and retrieve application configuration.
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
// Store configuration
|
|
511
|
+
const config = {
|
|
512
|
+
theme: 'dark',
|
|
513
|
+
language: 'en',
|
|
514
|
+
features: {
|
|
515
|
+
betaFeatures: true,
|
|
516
|
+
analytics: false
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
await leader.use(new oAddress('o://disk'), {
|
|
521
|
+
method: 'put',
|
|
522
|
+
params: {
|
|
523
|
+
key: 'app-config',
|
|
524
|
+
value: JSON.stringify(config)
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Retrieve configuration
|
|
529
|
+
const result = await leader.use(new oAddress('o://disk/app-config'));
|
|
530
|
+
const loadedConfig = JSON.parse(result.result.data.value);
|
|
531
|
+
|
|
532
|
+
// Update configuration
|
|
533
|
+
loadedConfig.theme = 'light';
|
|
534
|
+
await leader.use(new oAddress('o://disk'), {
|
|
535
|
+
method: 'put',
|
|
536
|
+
params: {
|
|
537
|
+
key: 'app-config',
|
|
538
|
+
value: JSON.stringify(loadedConfig)
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
### Use Case 2: Secure Credential Storage {#secure-credentials}
|
|
546
|
+
|
|
547
|
+
Store API keys and sensitive data encrypted.
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
// Store credentials securely
|
|
551
|
+
await leader.use(new oAddress('o://secure'), {
|
|
552
|
+
method: 'put',
|
|
553
|
+
params: {
|
|
554
|
+
key: 'stripe-keys',
|
|
555
|
+
value: JSON.stringify({
|
|
556
|
+
publishableKey: 'pk_live_xxxx',
|
|
557
|
+
secretKey: 'sk_live_xxxx',
|
|
558
|
+
webhookSecret: 'whsec_xxxx'
|
|
559
|
+
})
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Retrieve when needed (auto-decrypted)
|
|
564
|
+
const result = await leader.use(new oAddress('o://secure/stripe-keys'));
|
|
565
|
+
const keys = JSON.parse(result.result.data.value);
|
|
566
|
+
|
|
567
|
+
// Use in your application
|
|
568
|
+
const stripe = new Stripe(keys.secretKey);
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
### Use Case 3: Caching with Memory Storage {#caching}
|
|
574
|
+
|
|
575
|
+
Fast temporary storage for computed values.
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
// Check cache first
|
|
579
|
+
const cached = await leader.use(new oAddress('o://memory'), {
|
|
580
|
+
method: 'has',
|
|
581
|
+
params: { key: 'expensive-computation' }
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
if (cached.result.data.data) {
|
|
585
|
+
// Use cached value
|
|
586
|
+
const result = await leader.use(
|
|
587
|
+
new oAddress('o://memory/expensive-computation')
|
|
588
|
+
);
|
|
589
|
+
return JSON.parse(result.result.data.value);
|
|
590
|
+
} else {
|
|
591
|
+
// Compute and cache
|
|
592
|
+
const computed = performExpensiveComputation();
|
|
593
|
+
await leader.use(new oAddress('o://memory'), {
|
|
594
|
+
method: 'put',
|
|
595
|
+
params: {
|
|
596
|
+
key: 'expensive-computation',
|
|
597
|
+
value: JSON.stringify(computed)
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
return computed;
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
### Use Case 4: Large Document Processing {#large-documents}
|
|
607
|
+
|
|
608
|
+
Process large files with AI-powered summarization.
|
|
609
|
+
|
|
610
|
+
```typescript
|
|
611
|
+
// Read large codebase file
|
|
612
|
+
const sourceCode = await fs.readFile('src/app.ts', 'utf-8');
|
|
613
|
+
// Assume sourceCode is 100KB
|
|
614
|
+
|
|
615
|
+
// Store with intent
|
|
616
|
+
const stored = await leader.use(new oAddress('o://placeholder'), {
|
|
617
|
+
method: 'put',
|
|
618
|
+
params: {
|
|
619
|
+
key: 'source-app',
|
|
620
|
+
value: sourceCode,
|
|
621
|
+
intent: 'Refactor the authentication logic to use JWT tokens'
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
console.log(stored.summary);
|
|
626
|
+
// "This TypeScript application uses Express.js with session-based authentication.
|
|
627
|
+
// The authentication logic is in the AuthController class (lines 45-123).
|
|
628
|
+
// Current implementation uses cookies and express-session middleware..."
|
|
629
|
+
|
|
630
|
+
// Agent can now work with summary instead of full 100KB
|
|
631
|
+
// Only retrieve full content if absolutely necessary
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
### Use Case 5: Multi-Provider Data Management {#multi-provider}
|
|
637
|
+
|
|
638
|
+
Use different providers for different data types.
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
class DataManager {
|
|
642
|
+
constructor(private leader: oAddress) {}
|
|
643
|
+
|
|
644
|
+
// Temporary data -> Memory
|
|
645
|
+
async cacheSessionData(userId: string, data: any) {
|
|
646
|
+
await this.leader.use(new oAddress('o://memory'), {
|
|
647
|
+
method: 'put',
|
|
648
|
+
params: {
|
|
649
|
+
key: `session-${userId}`,
|
|
650
|
+
value: JSON.stringify(data)
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// User preferences -> Disk
|
|
656
|
+
async saveUserPreferences(userId: string, prefs: any) {
|
|
657
|
+
await this.leader.use(new oAddress('o://disk'), {
|
|
658
|
+
method: 'put',
|
|
659
|
+
params: {
|
|
660
|
+
key: `prefs-${userId}`,
|
|
661
|
+
value: JSON.stringify(prefs)
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Credentials -> Secure
|
|
667
|
+
async saveUserCredentials(userId: string, credentials: any) {
|
|
668
|
+
await this.leader.use(new oAddress('o://secure'), {
|
|
669
|
+
method: 'put',
|
|
670
|
+
params: {
|
|
671
|
+
key: `creds-${userId}`,
|
|
672
|
+
value: JSON.stringify(credentials)
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Large documents -> Placeholder
|
|
678
|
+
async saveDocument(docId: string, content: string, intent: string) {
|
|
679
|
+
return await this.leader.use(new oAddress('o://placeholder'), {
|
|
680
|
+
method: 'put',
|
|
681
|
+
params: {
|
|
682
|
+
key: docId,
|
|
683
|
+
value: content,
|
|
684
|
+
intent
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
## Integration Examples {#integration-examples}
|
|
692
|
+
|
|
693
|
+
### With o-node {#integration-o-node}
|
|
694
|
+
|
|
695
|
+
Use storage in a custom node.
|
|
696
|
+
|
|
697
|
+
```typescript
|
|
698
|
+
import { oNodeTool } from '@olane/o-node';
|
|
699
|
+
import { oAddress } from '@olane/o-core';
|
|
700
|
+
|
|
701
|
+
class MyCustomNode extends oNodeTool {
|
|
702
|
+
async _tool_save_config(request: oRequest) {
|
|
703
|
+
const { configData } = request.params;
|
|
704
|
+
|
|
705
|
+
// Store configuration using disk storage
|
|
706
|
+
await this.use(new oAddress('o://disk'), {
|
|
707
|
+
method: 'put',
|
|
708
|
+
params: {
|
|
709
|
+
key: 'my-node-config',
|
|
710
|
+
value: JSON.stringify(configData)
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
return { success: true };
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
async _tool_load_config(request: oRequest) {
|
|
718
|
+
// Retrieve configuration
|
|
719
|
+
const result = await this.use(new oAddress('o://disk/my-node-config'));
|
|
720
|
+
return JSON.parse(result.result.data.value);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
### With o-lane {#integration-o-lane}
|
|
728
|
+
|
|
729
|
+
Use storage in an intelligent node.
|
|
730
|
+
|
|
731
|
+
```typescript
|
|
732
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
733
|
+
import { oAddress } from '@olane/o-core';
|
|
734
|
+
|
|
735
|
+
class IntelligentDataNode extends oLaneTool {
|
|
736
|
+
async _tool_analyze_document(request: oRequest) {
|
|
737
|
+
const { documentContent, analysisGoal } = request.params;
|
|
738
|
+
|
|
739
|
+
// Store document with intent using placeholder
|
|
740
|
+
const stored = await this.use(new oAddress('o://placeholder'), {
|
|
741
|
+
method: 'put',
|
|
742
|
+
params: {
|
|
743
|
+
key: `doc-${Date.now()}`,
|
|
744
|
+
value: documentContent,
|
|
745
|
+
intent: analysisGoal
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
// Return summary for further processing
|
|
750
|
+
return {
|
|
751
|
+
summary: stored.summary,
|
|
752
|
+
address: stored.address,
|
|
753
|
+
instructions: stored.instructions
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
### Standalone Usage {#standalone-usage}
|
|
762
|
+
|
|
763
|
+
Use storage providers independently.
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
import { MemoryStorageProvider } from '@olane/o-storage';
|
|
767
|
+
import { oLeaderNode } from '@olane/o-leader';
|
|
768
|
+
import { oAddress } from '@olane/o-core';
|
|
769
|
+
|
|
770
|
+
// Setup
|
|
771
|
+
const leader = new oLeaderNode({
|
|
772
|
+
parent: null,
|
|
773
|
+
leader: null
|
|
774
|
+
});
|
|
775
|
+
await leader.start();
|
|
776
|
+
|
|
777
|
+
// Create standalone memory storage
|
|
778
|
+
const memory = new MemoryStorageProvider({
|
|
779
|
+
name: 'cache',
|
|
780
|
+
leader: leader.address
|
|
781
|
+
});
|
|
782
|
+
await memory.start();
|
|
783
|
+
|
|
784
|
+
// Use directly
|
|
785
|
+
await leader.use(new oAddress('o://memory'), {
|
|
786
|
+
method: 'put',
|
|
787
|
+
params: { key: 'test', value: 'data' }
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
const result = await leader.use(new oAddress('o://memory/test'));
|
|
791
|
+
console.log(result.result.data.value); // 'data'
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
## Troubleshooting {#troubleshooting}
|
|
795
|
+
|
|
796
|
+
### Error: "Failed to store data: EACCES: permission denied" {#error-eacces}
|
|
797
|
+
|
|
798
|
+
**Problem**: Disk storage can't write to storage directory.
|
|
799
|
+
|
|
800
|
+
**Solution**:
|
|
801
|
+
```bash
|
|
802
|
+
# Check permissions on default storage directory
|
|
803
|
+
ls -la ~/.olane/
|
|
804
|
+
|
|
805
|
+
# Fix permissions
|
|
806
|
+
chmod 755 ~/.olane
|
|
807
|
+
chmod 755 ~/.olane/storage
|
|
808
|
+
|
|
809
|
+
# Or specify custom directory with write permissions
|
|
810
|
+
const disk = new DiskStorageProvider({
|
|
811
|
+
name: 'disk',
|
|
812
|
+
leader: leaderAddress,
|
|
813
|
+
storageDir: '/path/with/write/permissions'
|
|
814
|
+
});
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
### Error: "Cannot find node with address o://encryption" {#error-no-encryption}
|
|
820
|
+
|
|
821
|
+
**Problem**: Secure storage requires `o://encryption` node.
|
|
822
|
+
|
|
823
|
+
**Solution**:
|
|
824
|
+
```typescript
|
|
825
|
+
// Ensure encryption node is running before using secure storage
|
|
826
|
+
import { EncryptionTool } from '@olane/o-encryption';
|
|
827
|
+
|
|
828
|
+
const encryption = new EncryptionTool({
|
|
829
|
+
parent: leaderAddress,
|
|
830
|
+
leader: leaderAddress
|
|
831
|
+
});
|
|
832
|
+
await encryption.start();
|
|
833
|
+
|
|
834
|
+
// Now secure storage will work
|
|
835
|
+
const result = await leader.use(new oAddress('o://secure'), {
|
|
836
|
+
method: 'put',
|
|
837
|
+
params: { key: 'secret', value: 'data' }
|
|
838
|
+
});
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
---
|
|
842
|
+
|
|
843
|
+
### Error: "Cannot find node with address o://intelligence" {#error-no-intelligence}
|
|
844
|
+
|
|
845
|
+
**Problem**: Placeholder storage requires `o://intelligence` node.
|
|
846
|
+
|
|
847
|
+
**Solution**:
|
|
848
|
+
```typescript
|
|
849
|
+
// Ensure intelligence node is running before using placeholder storage
|
|
850
|
+
import { IntelligenceTool } from '@olane/o-intelligence';
|
|
851
|
+
|
|
852
|
+
const intelligence = new IntelligenceTool({
|
|
853
|
+
parent: leaderAddress,
|
|
854
|
+
leader: leaderAddress
|
|
855
|
+
});
|
|
856
|
+
await intelligence.start();
|
|
857
|
+
|
|
858
|
+
// Now placeholder storage will work
|
|
859
|
+
const result = await leader.use(new oAddress('o://placeholder'), {
|
|
860
|
+
method: 'put',
|
|
861
|
+
params: {
|
|
862
|
+
key: 'doc',
|
|
863
|
+
value: largeDocument,
|
|
864
|
+
intent: 'Summarize key points'
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
### Issue: Memory storage data lost on restart {#memory-data-lost}
|
|
872
|
+
|
|
873
|
+
**Problem**: Data stored in memory storage disappears after restart.
|
|
874
|
+
|
|
875
|
+
**Solution**: This is expected behavior. Memory storage is volatile.
|
|
876
|
+
|
|
877
|
+
```typescript
|
|
878
|
+
// For persistent data, use disk storage instead
|
|
879
|
+
await leader.use(new oAddress('o://disk'), {
|
|
880
|
+
method: 'put',
|
|
881
|
+
params: { key: 'persistent-data', value: data }
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
// Or implement your own persistence pattern
|
|
885
|
+
class PersistentCache {
|
|
886
|
+
async set(key: string, value: string) {
|
|
887
|
+
// Store in memory for speed
|
|
888
|
+
await leader.use(new oAddress('o://memory'), {
|
|
889
|
+
method: 'put',
|
|
890
|
+
params: { key, value }
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
// Also persist to disk
|
|
894
|
+
await leader.use(new oAddress('o://disk'), {
|
|
895
|
+
method: 'put',
|
|
896
|
+
params: { key: `cache-${key}`, value }
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
async get(key: string) {
|
|
901
|
+
// Try memory first
|
|
902
|
+
const memResult = await leader.use(new oAddress('o://memory'), {
|
|
903
|
+
method: 'has',
|
|
904
|
+
params: { key }
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
if (memResult.result.data.data) {
|
|
908
|
+
return await leader.use(new oAddress('o://memory/') + key);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// Fall back to disk
|
|
912
|
+
return await leader.use(new oAddress('o://disk/cache-') + key);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
### Issue: Placeholder storage using too many tokens {#placeholder-tokens}
|
|
920
|
+
|
|
921
|
+
**Problem**: AI summarization costs too many tokens for large documents.
|
|
922
|
+
|
|
923
|
+
**Solution**: Documents are truncated to 50,000 characters automatically.
|
|
924
|
+
|
|
925
|
+
```typescript
|
|
926
|
+
// For very large documents, pre-process them
|
|
927
|
+
const largeDoc = await fs.readFile('huge-file.txt', 'utf-8');
|
|
928
|
+
|
|
929
|
+
if (largeDoc.length > 50000) {
|
|
930
|
+
// Option 1: Store relevant section only
|
|
931
|
+
const relevantSection = extractRelevantSection(largeDoc);
|
|
932
|
+
await leader.use(new oAddress('o://placeholder'), {
|
|
933
|
+
method: 'put',
|
|
934
|
+
params: {
|
|
935
|
+
key: 'doc-section',
|
|
936
|
+
value: relevantSection,
|
|
937
|
+
intent: 'Find API endpoints'
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
// Option 2: Use regular disk storage for full content
|
|
942
|
+
await leader.use(new oAddress('o://disk'), {
|
|
943
|
+
method: 'put',
|
|
944
|
+
params: {
|
|
945
|
+
key: 'full-doc',
|
|
946
|
+
value: largeDoc
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
// Store summary separately
|
|
951
|
+
const summary = manualSummary(largeDoc);
|
|
952
|
+
await leader.use(new oAddress('o://memory'), {
|
|
953
|
+
method: 'put',
|
|
954
|
+
params: {
|
|
955
|
+
key: 'doc-summary',
|
|
956
|
+
value: summary
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
## Package Information {#package-info}
|
|
963
|
+
|
|
964
|
+
**Package Name**: `@olane/o-storage`
|
|
965
|
+
**Version**: 0.7.2
|
|
966
|
+
**License**: ISC
|
|
967
|
+
**Repository**: [github.com/olane-labs/olane](https://github.com/olane-labs/olane)
|
|
968
|
+
|
|
969
|
+
### Dependencies {#dependencies}
|
|
970
|
+
|
|
971
|
+
**Peer Dependencies** (required):
|
|
972
|
+
- `@olane/o-core` - Core types and utilities
|
|
973
|
+
- `@olane/o-protocol` - Protocol definitions
|
|
974
|
+
- `@olane/o-tool` - Tool base classes
|
|
975
|
+
- `@olane/o-node` - Node functionality
|
|
976
|
+
- `@olane/o-lane` - Intelligence capabilities
|
|
977
|
+
- `@olane/o-config` - Configuration management
|
|
978
|
+
|
|
979
|
+
**Optional Runtime Dependencies**:
|
|
980
|
+
- `@olane/o-encryption` - Required for `SecureStorageProvider`
|
|
981
|
+
- `@olane/o-intelligence` - Required for `PlaceholderTool`
|
|
982
|
+
|
|
983
|
+
### Installation {#installation}
|
|
984
|
+
|
|
985
|
+
```bash
|
|
986
|
+
# Install storage package
|
|
987
|
+
npm install @olane/o-storage
|
|
988
|
+
|
|
989
|
+
# Install peer dependencies
|
|
990
|
+
npm install @olane/o-core @olane/o-protocol @olane/o-tool @olane/o-node @olane/o-lane @olane/o-config
|
|
991
|
+
|
|
992
|
+
# Optional: For secure storage
|
|
993
|
+
npm install @olane/o-encryption
|
|
994
|
+
|
|
995
|
+
# Optional: For placeholder storage
|
|
996
|
+
npm install @olane/o-intelligence
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
## Related {#related}
|
|
1000
|
+
|
|
1001
|
+
- **Package**: [o-core](/packages/o-core) - Core addressing and request types
|
|
1002
|
+
- **Package**: [o-node](/packages/o-node) - Node creation and management
|
|
1003
|
+
- **Package**: [o-lane](/packages/o-lane) - Intelligence and capability loops
|
|
1004
|
+
- **Package**: [o-leader](/packages/o-leader) - Service discovery and coordination
|
|
1005
|
+
- **Package**: [o-intelligence](/packages/o-intelligence) - AI integration for placeholder storage
|
|
1006
|
+
- **Concept**: [Tools, Nodes, and Applications](/concepts/tools-nodes-applications) - Understanding architectural levels
|
|
1007
|
+
- **Guide**: [Building Applications](/concepts/applications) - Multi-node coordination patterns
|
|
1008
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-storage",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"url": "git+https://github.com/olane-labs/olane.git"
|
|
34
34
|
},
|
|
35
35
|
"author": "oLane Inc.",
|
|
36
|
-
"license": "
|
|
36
|
+
"license": "(MIT OR Apache-2.0)",
|
|
37
37
|
"description": "oLane storage tool",
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@eslint/eslintrc": "^3.3.1",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"typescript": "5.4.5"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@olane/o-config": "^0.7.
|
|
60
|
-
"@olane/o-core": "^0.7.
|
|
61
|
-
"@olane/o-lane": "^0.7.
|
|
62
|
-
"@olane/o-node": "^0.7.
|
|
63
|
-
"@olane/o-protocol": "^0.7.
|
|
64
|
-
"@olane/o-tool": "^0.7.
|
|
59
|
+
"@olane/o-config": "^0.7.3",
|
|
60
|
+
"@olane/o-core": "^0.7.3",
|
|
61
|
+
"@olane/o-lane": "^0.7.3",
|
|
62
|
+
"@olane/o-node": "^0.7.3",
|
|
63
|
+
"@olane/o-protocol": "^0.7.3",
|
|
64
|
+
"@olane/o-tool": "^0.7.3"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"debug": "^4.4.1",
|