remembra 0.7.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 +179 -0
- package/dist/index.d.mts +295 -0
- package/dist/index.d.ts +295 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +340 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Remembra TypeScript SDK
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript SDK for [Remembra](https://remembra.dev) - the AI Memory Layer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install remembra
|
|
9
|
+
# or
|
|
10
|
+
yarn add remembra
|
|
11
|
+
# or
|
|
12
|
+
pnpm add remembra
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Remembra } from 'remembra';
|
|
19
|
+
|
|
20
|
+
// Initialize client
|
|
21
|
+
const memory = new Remembra({
|
|
22
|
+
url: 'http://localhost:8787', // Self-hosted
|
|
23
|
+
apiKey: 'your-api-key', // Optional for self-hosted
|
|
24
|
+
userId: 'user_123',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Store a memory
|
|
28
|
+
const stored = await memory.store('User prefers dark mode and hates long emails');
|
|
29
|
+
console.log(stored.extracted_facts);
|
|
30
|
+
// ['User prefers dark mode', 'User hates long emails']
|
|
31
|
+
|
|
32
|
+
// Recall memories
|
|
33
|
+
const result = await memory.recall('What are user preferences?');
|
|
34
|
+
console.log(result.context);
|
|
35
|
+
// 'User prefers dark mode. User hates long emails.'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Conversation Ingestion
|
|
39
|
+
|
|
40
|
+
Automatically extract memories from conversations:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const result = await memory.ingestConversation([
|
|
44
|
+
{ role: 'user', content: 'My wife Suzan and I are planning a trip to Japan' },
|
|
45
|
+
{ role: 'assistant', content: 'That sounds exciting! When are you going?' },
|
|
46
|
+
{ role: 'user', content: 'We are thinking April next year' },
|
|
47
|
+
], {
|
|
48
|
+
minImportance: 0.5,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(`Extracted: ${result.stats.facts_extracted} facts`);
|
|
52
|
+
console.log(`Stored: ${result.stats.facts_stored} memories`);
|
|
53
|
+
|
|
54
|
+
// Facts extracted:
|
|
55
|
+
// - "User's wife is named Suzan"
|
|
56
|
+
// - "User is planning a trip to Japan in April"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## API Reference
|
|
60
|
+
|
|
61
|
+
### Constructor
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
new Remembra(config: RemembraConfig)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
| Option | Type | Default | Description |
|
|
68
|
+
|--------|------|---------|-------------|
|
|
69
|
+
| `url` | string | `http://localhost:8787` | Remembra server URL |
|
|
70
|
+
| `apiKey` | string | - | API key for authentication |
|
|
71
|
+
| `userId` | string | **required** | User ID for memory isolation |
|
|
72
|
+
| `project` | string | `default` | Project namespace |
|
|
73
|
+
| `timeout` | number | `30000` | Request timeout (ms) |
|
|
74
|
+
| `debug` | boolean | `false` | Enable debug logging |
|
|
75
|
+
|
|
76
|
+
### Methods
|
|
77
|
+
|
|
78
|
+
#### `store(content, options?)`
|
|
79
|
+
|
|
80
|
+
Store a new memory.
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const result = await memory.store('John is the CEO of Acme Corp', {
|
|
84
|
+
metadata: { source: 'meeting' },
|
|
85
|
+
ttl: '30d', // Expires in 30 days
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### `recall(query, options?)`
|
|
90
|
+
|
|
91
|
+
Recall relevant memories.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const result = await memory.recall('Who is John?', {
|
|
95
|
+
limit: 10,
|
|
96
|
+
threshold: 0.5,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log(result.context); // Synthesized context
|
|
100
|
+
console.log(result.memories); // Individual memories
|
|
101
|
+
console.log(result.entities); // Related entities
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### `ingestConversation(messages, options?)`
|
|
105
|
+
|
|
106
|
+
Ingest a conversation and extract memories.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const result = await memory.ingestConversation(messages, {
|
|
110
|
+
sessionId: 'session_123',
|
|
111
|
+
extractFrom: 'both', // 'user' | 'assistant' | 'both'
|
|
112
|
+
minImportance: 0.5,
|
|
113
|
+
dedupe: true,
|
|
114
|
+
store: true, // false for dry-run
|
|
115
|
+
infer: true, // false to store raw messages
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### `forget(options)`
|
|
120
|
+
|
|
121
|
+
Delete memories (GDPR-compliant).
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Delete specific memory
|
|
125
|
+
await memory.forget({ memoryId: 'mem_123' });
|
|
126
|
+
|
|
127
|
+
// Delete all about an entity
|
|
128
|
+
await memory.forget({ entity: 'John' });
|
|
129
|
+
|
|
130
|
+
// Delete all user memories
|
|
131
|
+
await memory.forget();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### `get(memoryId)`
|
|
135
|
+
|
|
136
|
+
Get a specific memory by ID.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const mem = await memory.get('mem_123');
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### `health()`
|
|
143
|
+
|
|
144
|
+
Check server health.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const health = await memory.health();
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Error Handling
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import {
|
|
154
|
+
RemembraError,
|
|
155
|
+
AuthenticationError,
|
|
156
|
+
RateLimitError,
|
|
157
|
+
ValidationError,
|
|
158
|
+
} from 'remembra';
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
await memory.store(content);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error instanceof AuthenticationError) {
|
|
164
|
+
// Handle auth error
|
|
165
|
+
} else if (error instanceof RateLimitError) {
|
|
166
|
+
// Wait and retry
|
|
167
|
+
console.log(`Retry after ${error.retryAfter} seconds`);
|
|
168
|
+
} else if (error instanceof ValidationError) {
|
|
169
|
+
// Handle validation error
|
|
170
|
+
} else if (error instanceof RemembraError) {
|
|
171
|
+
// Generic Remembra error
|
|
172
|
+
console.log(error.status, error.message);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remembra TypeScript SDK Types
|
|
3
|
+
*/
|
|
4
|
+
interface RemembraConfig {
|
|
5
|
+
/** Remembra server URL */
|
|
6
|
+
url?: string;
|
|
7
|
+
/** API key for authentication */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** User ID for memory operations */
|
|
10
|
+
userId: string;
|
|
11
|
+
/** Project namespace */
|
|
12
|
+
project?: string;
|
|
13
|
+
/** Request timeout in milliseconds */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
/** Enable debug logging */
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface EntityRef {
|
|
19
|
+
id: string;
|
|
20
|
+
canonical_name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
confidence: number;
|
|
23
|
+
}
|
|
24
|
+
interface Memory {
|
|
25
|
+
id: string;
|
|
26
|
+
content: string;
|
|
27
|
+
relevance: number;
|
|
28
|
+
created_at: string;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
interface StoreOptions {
|
|
32
|
+
/** Optional key-value metadata */
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
/** Time-to-live (e.g., "30d", "1y") */
|
|
35
|
+
ttl?: string;
|
|
36
|
+
}
|
|
37
|
+
interface StoreResult {
|
|
38
|
+
id: string;
|
|
39
|
+
extracted_facts: string[];
|
|
40
|
+
entities: EntityRef[];
|
|
41
|
+
}
|
|
42
|
+
interface RecallOptions {
|
|
43
|
+
/** Maximum results (1-50) */
|
|
44
|
+
limit?: number;
|
|
45
|
+
/** Minimum relevance threshold (0.0-1.0) */
|
|
46
|
+
threshold?: number;
|
|
47
|
+
/** Maximum tokens in context */
|
|
48
|
+
maxTokens?: number;
|
|
49
|
+
/** Enable hybrid search */
|
|
50
|
+
enableHybrid?: boolean;
|
|
51
|
+
/** Enable reranking */
|
|
52
|
+
enableRerank?: boolean;
|
|
53
|
+
}
|
|
54
|
+
interface RecallResult {
|
|
55
|
+
context: string;
|
|
56
|
+
memories: Memory[];
|
|
57
|
+
entities: EntityRef[];
|
|
58
|
+
}
|
|
59
|
+
interface ForgetOptions {
|
|
60
|
+
/** Delete specific memory by ID */
|
|
61
|
+
memoryId?: string;
|
|
62
|
+
/** Delete all memories about an entity */
|
|
63
|
+
entity?: string;
|
|
64
|
+
}
|
|
65
|
+
interface ForgetResult {
|
|
66
|
+
deleted_memories: number;
|
|
67
|
+
deleted_entities: number;
|
|
68
|
+
deleted_relationships: number;
|
|
69
|
+
}
|
|
70
|
+
interface Message {
|
|
71
|
+
/** Message role: user, assistant, or system */
|
|
72
|
+
role: 'user' | 'assistant' | 'system';
|
|
73
|
+
/** Message content */
|
|
74
|
+
content: string;
|
|
75
|
+
/** Optional speaker name */
|
|
76
|
+
name?: string;
|
|
77
|
+
/** Optional timestamp (ISO format) */
|
|
78
|
+
timestamp?: string;
|
|
79
|
+
/** Optional metadata */
|
|
80
|
+
metadata?: Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
interface IngestOptions {
|
|
83
|
+
/** Session ID for grouping conversations */
|
|
84
|
+
sessionId?: string;
|
|
85
|
+
/** Which messages to extract from */
|
|
86
|
+
extractFrom?: 'user' | 'assistant' | 'both';
|
|
87
|
+
/** Minimum importance threshold (0.0-1.0) */
|
|
88
|
+
minImportance?: number;
|
|
89
|
+
/** Enable deduplication */
|
|
90
|
+
dedupe?: boolean;
|
|
91
|
+
/** Store results (false for dry-run) */
|
|
92
|
+
store?: boolean;
|
|
93
|
+
/** Enable extraction (false to store raw) */
|
|
94
|
+
infer?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface ExtractedFact {
|
|
97
|
+
content: string;
|
|
98
|
+
confidence: number;
|
|
99
|
+
importance: number;
|
|
100
|
+
source_message_index: number;
|
|
101
|
+
speaker: string | null;
|
|
102
|
+
stored: boolean;
|
|
103
|
+
memory_id: string | null;
|
|
104
|
+
action: 'add' | 'update' | 'delete' | 'noop' | 'skipped';
|
|
105
|
+
action_reason: string | null;
|
|
106
|
+
}
|
|
107
|
+
interface ExtractedEntity {
|
|
108
|
+
name: string;
|
|
109
|
+
type: string;
|
|
110
|
+
relationship: string | null;
|
|
111
|
+
}
|
|
112
|
+
interface IngestStats {
|
|
113
|
+
messages_processed: number;
|
|
114
|
+
facts_extracted: number;
|
|
115
|
+
facts_stored: number;
|
|
116
|
+
facts_updated: number;
|
|
117
|
+
facts_deduped: number;
|
|
118
|
+
facts_skipped: number;
|
|
119
|
+
entities_found: number;
|
|
120
|
+
processing_time_ms: number;
|
|
121
|
+
}
|
|
122
|
+
interface IngestResult {
|
|
123
|
+
status: 'ok' | 'partial' | 'error';
|
|
124
|
+
session_id: string | null;
|
|
125
|
+
facts: ExtractedFact[];
|
|
126
|
+
entities: ExtractedEntity[];
|
|
127
|
+
stats: IngestStats;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Remembra TypeScript Client
|
|
132
|
+
*
|
|
133
|
+
* Main interface for the Remembra AI Memory Layer.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* import { Remembra } from 'remembra';
|
|
138
|
+
*
|
|
139
|
+
* const memory = new Remembra({
|
|
140
|
+
* url: 'http://localhost:8787',
|
|
141
|
+
* apiKey: 'your-api-key',
|
|
142
|
+
* userId: 'user_123',
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* // Store a memory
|
|
146
|
+
* const stored = await memory.store('User prefers dark mode');
|
|
147
|
+
*
|
|
148
|
+
* // Recall memories
|
|
149
|
+
* const result = await memory.recall('What are user preferences?');
|
|
150
|
+
* console.log(result.context);
|
|
151
|
+
*
|
|
152
|
+
* // Ingest a conversation
|
|
153
|
+
* const ingestResult = await memory.ingestConversation([
|
|
154
|
+
* { role: 'user', content: 'My name is John' },
|
|
155
|
+
* { role: 'assistant', content: 'Nice to meet you, John!' },
|
|
156
|
+
* ]);
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
declare class Remembra {
|
|
161
|
+
private readonly url;
|
|
162
|
+
private readonly apiKey?;
|
|
163
|
+
private readonly userId;
|
|
164
|
+
private readonly project;
|
|
165
|
+
private readonly timeout;
|
|
166
|
+
private readonly debug;
|
|
167
|
+
constructor(config: RemembraConfig);
|
|
168
|
+
private log;
|
|
169
|
+
private request;
|
|
170
|
+
private sleep;
|
|
171
|
+
/**
|
|
172
|
+
* Store a new memory.
|
|
173
|
+
*
|
|
174
|
+
* @param content - Text content to memorize
|
|
175
|
+
* @param options - Optional metadata and TTL
|
|
176
|
+
* @returns Stored memory with extracted facts and entities
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const result = await memory.store('User prefers dark mode', {
|
|
181
|
+
* metadata: { source: 'settings' },
|
|
182
|
+
* ttl: '30d',
|
|
183
|
+
* });
|
|
184
|
+
* console.log(result.extracted_facts);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
store(content: string, options?: StoreOptions): Promise<StoreResult>;
|
|
188
|
+
/**
|
|
189
|
+
* Recall memories relevant to a query.
|
|
190
|
+
*
|
|
191
|
+
* @param query - Natural language query
|
|
192
|
+
* @param options - Recall options (limit, threshold, etc.)
|
|
193
|
+
* @returns Context string and matching memories
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const result = await memory.recall('What are user preferences?');
|
|
198
|
+
* console.log(result.context); // Synthesized context
|
|
199
|
+
* console.log(result.memories); // Individual memories
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
recall(query: string, options?: RecallOptions): Promise<RecallResult>;
|
|
203
|
+
/**
|
|
204
|
+
* Get a specific memory by ID.
|
|
205
|
+
*
|
|
206
|
+
* @param memoryId - Memory ID
|
|
207
|
+
* @returns Memory details
|
|
208
|
+
*/
|
|
209
|
+
get(memoryId: string): Promise<Memory>;
|
|
210
|
+
/**
|
|
211
|
+
* Forget (delete) memories.
|
|
212
|
+
*
|
|
213
|
+
* @param options - What to delete (memoryId, entity, or all)
|
|
214
|
+
* @returns Deletion counts
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* // Delete specific memory
|
|
219
|
+
* await memory.forget({ memoryId: 'mem_123' });
|
|
220
|
+
*
|
|
221
|
+
* // Delete all about an entity
|
|
222
|
+
* await memory.forget({ entity: 'John' });
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
forget(options?: ForgetOptions): Promise<ForgetResult>;
|
|
226
|
+
/**
|
|
227
|
+
* Ingest a conversation and automatically extract memories.
|
|
228
|
+
*
|
|
229
|
+
* This is the primary method for AI agents to add conversation context
|
|
230
|
+
* to persistent memory without manually calling store for each fact.
|
|
231
|
+
*
|
|
232
|
+
* @param messages - Array of conversation messages
|
|
233
|
+
* @param options - Ingestion options
|
|
234
|
+
* @returns Extracted facts, entities, and stats
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const result = await memory.ingestConversation([
|
|
239
|
+
* { role: 'user', content: 'My name is John and I work at Google' },
|
|
240
|
+
* { role: 'assistant', content: 'Nice to meet you, John!' },
|
|
241
|
+
* ], {
|
|
242
|
+
* minImportance: 0.5,
|
|
243
|
+
* });
|
|
244
|
+
*
|
|
245
|
+
* console.log(`Extracted ${result.stats.facts_extracted} facts`);
|
|
246
|
+
* console.log(`Stored ${result.stats.facts_stored} new memories`);
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
ingestConversation(messages: Message[], options?: IngestOptions): Promise<IngestResult>;
|
|
250
|
+
/**
|
|
251
|
+
* Check server health.
|
|
252
|
+
*
|
|
253
|
+
* @returns Health status
|
|
254
|
+
*/
|
|
255
|
+
health(): Promise<Record<string, unknown>>;
|
|
256
|
+
/**
|
|
257
|
+
* List entities for the current user.
|
|
258
|
+
*
|
|
259
|
+
* @returns Array of entities
|
|
260
|
+
*/
|
|
261
|
+
listEntities(): Promise<EntityRef[]>;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Remembra SDK Error Classes
|
|
266
|
+
*/
|
|
267
|
+
declare class RemembraError extends Error {
|
|
268
|
+
readonly status?: number;
|
|
269
|
+
readonly code?: string;
|
|
270
|
+
constructor(message: string, status?: number, code?: string);
|
|
271
|
+
}
|
|
272
|
+
declare class AuthenticationError extends RemembraError {
|
|
273
|
+
constructor(message?: string);
|
|
274
|
+
}
|
|
275
|
+
declare class NotFoundError extends RemembraError {
|
|
276
|
+
constructor(message?: string);
|
|
277
|
+
}
|
|
278
|
+
declare class ValidationError extends RemembraError {
|
|
279
|
+
constructor(message: string);
|
|
280
|
+
}
|
|
281
|
+
declare class RateLimitError extends RemembraError {
|
|
282
|
+
readonly retryAfter?: number;
|
|
283
|
+
constructor(message?: string, retryAfter?: number);
|
|
284
|
+
}
|
|
285
|
+
declare class ServerError extends RemembraError {
|
|
286
|
+
constructor(message?: string);
|
|
287
|
+
}
|
|
288
|
+
declare class NetworkError extends RemembraError {
|
|
289
|
+
constructor(message?: string);
|
|
290
|
+
}
|
|
291
|
+
declare class TimeoutError extends RemembraError {
|
|
292
|
+
constructor(message?: string);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export { AuthenticationError, type EntityRef, type ExtractedEntity, type ExtractedFact, type ForgetOptions, type ForgetResult, type IngestOptions, type IngestResult, type IngestStats, type Memory, type Message, NetworkError, NotFoundError, RateLimitError, type RecallOptions, type RecallResult, Remembra, type RemembraConfig, RemembraError, ServerError, type StoreOptions, type StoreResult, TimeoutError, ValidationError };
|