@lanonasis/memory-client 1.0.1 → 2.1.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/dist/core/index.d.ts +948 -0
- package/dist/core/index.js +1027 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/tsconfig.tsbuildinfo +1 -0
- package/dist/index.d.ts +703 -352
- package/dist/index.esm.js +1070 -277
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1098 -283
- package/dist/index.js.map +1 -1
- package/dist/node/index.d.ts +329 -0
- package/dist/node/index.js +647 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/tsconfig.tsbuildinfo +1 -0
- package/dist/presets/index.d.ts +146 -0
- package/dist/presets/index.js +234 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/tsconfig.tsbuildinfo +1 -0
- package/dist/react/index.d.ts +235 -0
- package/dist/react/index.js +333 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/tsconfig.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vue/index.d.ts +316 -0
- package/dist/vue/index.js +341 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/tsconfig.tsbuildinfo +1 -0
- package/package.json +67 -13
|
@@ -0,0 +1,1027 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Memory types supported by the service
|
|
5
|
+
*/
|
|
6
|
+
const MEMORY_TYPES = ['context', 'project', 'knowledge', 'reference', 'personal', 'workflow'];
|
|
7
|
+
/**
|
|
8
|
+
* Memory status values
|
|
9
|
+
*/
|
|
10
|
+
const MEMORY_STATUSES = ['active', 'archived', 'draft', 'deleted'];
|
|
11
|
+
/**
|
|
12
|
+
* Validation schemas using Zod
|
|
13
|
+
*/
|
|
14
|
+
const createMemorySchema = z.object({
|
|
15
|
+
title: z.string().min(1).max(500),
|
|
16
|
+
content: z.string().min(1).max(50000),
|
|
17
|
+
summary: z.string().max(1000).optional(),
|
|
18
|
+
memory_type: z.enum(MEMORY_TYPES).default('context'),
|
|
19
|
+
topic_id: z.string().uuid().optional(),
|
|
20
|
+
project_ref: z.string().max(100).optional(),
|
|
21
|
+
tags: z.array(z.string().min(1).max(50)).max(20).default([]),
|
|
22
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
23
|
+
});
|
|
24
|
+
const updateMemorySchema = z.object({
|
|
25
|
+
title: z.string().min(1).max(500).optional(),
|
|
26
|
+
content: z.string().min(1).max(50000).optional(),
|
|
27
|
+
summary: z.string().max(1000).optional(),
|
|
28
|
+
memory_type: z.enum(MEMORY_TYPES).optional(),
|
|
29
|
+
status: z.enum(MEMORY_STATUSES).optional(),
|
|
30
|
+
topic_id: z.string().uuid().nullable().optional(),
|
|
31
|
+
project_ref: z.string().max(100).nullable().optional(),
|
|
32
|
+
tags: z.array(z.string().min(1).max(50)).max(20).optional(),
|
|
33
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
34
|
+
});
|
|
35
|
+
const searchMemorySchema = z.object({
|
|
36
|
+
query: z.string().min(1).max(1000),
|
|
37
|
+
memory_types: z.array(z.enum(MEMORY_TYPES)).optional(),
|
|
38
|
+
tags: z.array(z.string()).optional(),
|
|
39
|
+
topic_id: z.string().uuid().optional(),
|
|
40
|
+
project_ref: z.string().optional(),
|
|
41
|
+
status: z.enum(MEMORY_STATUSES).default('active'),
|
|
42
|
+
limit: z.number().int().min(1).max(100).default(20),
|
|
43
|
+
threshold: z.number().min(0).max(1).default(0.7)
|
|
44
|
+
});
|
|
45
|
+
const createTopicSchema = z.object({
|
|
46
|
+
name: z.string().min(1).max(100),
|
|
47
|
+
description: z.string().max(500).optional(),
|
|
48
|
+
color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
49
|
+
icon: z.string().max(50).optional(),
|
|
50
|
+
parent_topic_id: z.string().uuid().optional()
|
|
51
|
+
});
|
|
52
|
+
// ========================================
|
|
53
|
+
// Intelligence Feature Types (v2.0)
|
|
54
|
+
// ========================================
|
|
55
|
+
/**
|
|
56
|
+
* Chunking strategies for content preprocessing
|
|
57
|
+
*/
|
|
58
|
+
const CHUNKING_STRATEGIES = ['semantic', 'fixed-size', 'paragraph', 'sentence', 'code-block'];
|
|
59
|
+
/**
|
|
60
|
+
* Content types detected or specified
|
|
61
|
+
*/
|
|
62
|
+
const CONTENT_TYPES = ['text', 'code', 'markdown', 'json', 'yaml'];
|
|
63
|
+
// ========================================
|
|
64
|
+
// Enhanced Search Types
|
|
65
|
+
// ========================================
|
|
66
|
+
/**
|
|
67
|
+
* Search modes for memory queries
|
|
68
|
+
*/
|
|
69
|
+
const SEARCH_MODES = ['vector', 'text', 'hybrid'];
|
|
70
|
+
// ========================================
|
|
71
|
+
// Validation Schemas for Intelligence
|
|
72
|
+
// ========================================
|
|
73
|
+
const preprocessingOptionsSchema = z.object({
|
|
74
|
+
chunking: z.object({
|
|
75
|
+
strategy: z.enum(CHUNKING_STRATEGIES).optional(),
|
|
76
|
+
maxChunkSize: z.number().int().min(100).max(10000).optional(),
|
|
77
|
+
overlap: z.number().int().min(0).max(500).optional()
|
|
78
|
+
}).optional(),
|
|
79
|
+
cleanContent: z.boolean().optional(),
|
|
80
|
+
extractMetadata: z.boolean().optional()
|
|
81
|
+
}).optional();
|
|
82
|
+
const enhancedSearchSchema = z.object({
|
|
83
|
+
query: z.string().min(1).max(1000),
|
|
84
|
+
type: z.enum(MEMORY_TYPES).optional(),
|
|
85
|
+
threshold: z.number().min(0).max(1).default(0.7),
|
|
86
|
+
limit: z.number().int().min(1).max(100).default(20),
|
|
87
|
+
search_mode: z.enum(SEARCH_MODES).default('hybrid'),
|
|
88
|
+
filters: z.object({
|
|
89
|
+
tags: z.array(z.string()).optional(),
|
|
90
|
+
project_id: z.string().uuid().optional(),
|
|
91
|
+
topic_id: z.string().uuid().optional(),
|
|
92
|
+
date_range: z.object({
|
|
93
|
+
from: z.string().optional(),
|
|
94
|
+
to: z.string().optional()
|
|
95
|
+
}).optional()
|
|
96
|
+
}).optional(),
|
|
97
|
+
include_chunks: z.boolean().default(false)
|
|
98
|
+
});
|
|
99
|
+
const analyticsDateRangeSchema = z.object({
|
|
100
|
+
from: z.string().optional(),
|
|
101
|
+
to: z.string().optional(),
|
|
102
|
+
group_by: z.enum(['day', 'week', 'month']).default('day')
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Core Utilities for Memory Client
|
|
107
|
+
* Browser-safe, no Node.js dependencies
|
|
108
|
+
*/
|
|
109
|
+
/**
|
|
110
|
+
* Safely parse JSON with detailed error reporting
|
|
111
|
+
* Prevents scattered try/catch blocks throughout the codebase
|
|
112
|
+
*/
|
|
113
|
+
function safeJsonParse(input) {
|
|
114
|
+
try {
|
|
115
|
+
const data = JSON.parse(input);
|
|
116
|
+
return { success: true, data };
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
const message = error instanceof Error
|
|
120
|
+
? error.message
|
|
121
|
+
: 'Unknown JSON parse error';
|
|
122
|
+
return { success: false, error: `Invalid JSON: ${message}` };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* HTTP status code to error code mapping
|
|
127
|
+
*/
|
|
128
|
+
function httpStatusToErrorCode(status) {
|
|
129
|
+
switch (status) {
|
|
130
|
+
case 400:
|
|
131
|
+
return 'VALIDATION_ERROR';
|
|
132
|
+
case 401:
|
|
133
|
+
return 'AUTH_ERROR';
|
|
134
|
+
case 403:
|
|
135
|
+
return 'FORBIDDEN';
|
|
136
|
+
case 404:
|
|
137
|
+
return 'NOT_FOUND';
|
|
138
|
+
case 408:
|
|
139
|
+
return 'TIMEOUT_ERROR';
|
|
140
|
+
case 409:
|
|
141
|
+
return 'CONFLICT';
|
|
142
|
+
case 429:
|
|
143
|
+
return 'RATE_LIMIT_ERROR';
|
|
144
|
+
case 500:
|
|
145
|
+
case 502:
|
|
146
|
+
case 503:
|
|
147
|
+
case 504:
|
|
148
|
+
return 'SERVER_ERROR';
|
|
149
|
+
default:
|
|
150
|
+
return 'API_ERROR';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Create a standardized error response from various error sources
|
|
155
|
+
*/
|
|
156
|
+
function createErrorResponse(message, code = 'API_ERROR', statusCode, details) {
|
|
157
|
+
return {
|
|
158
|
+
code,
|
|
159
|
+
message,
|
|
160
|
+
statusCode,
|
|
161
|
+
details,
|
|
162
|
+
timestamp: new Date().toISOString()
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create an error response from an HTTP response
|
|
167
|
+
*/
|
|
168
|
+
function createErrorFromResponse(status, statusText, body) {
|
|
169
|
+
const code = httpStatusToErrorCode(status);
|
|
170
|
+
// Try to extract message from response body
|
|
171
|
+
let message = `HTTP ${status}: ${statusText}`;
|
|
172
|
+
let details = undefined;
|
|
173
|
+
if (body && typeof body === 'object') {
|
|
174
|
+
const bodyObj = body;
|
|
175
|
+
if (typeof bodyObj.error === 'string') {
|
|
176
|
+
message = bodyObj.error;
|
|
177
|
+
}
|
|
178
|
+
else if (typeof bodyObj.message === 'string') {
|
|
179
|
+
message = bodyObj.message;
|
|
180
|
+
}
|
|
181
|
+
if (bodyObj.details) {
|
|
182
|
+
details = bodyObj.details;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return createErrorResponse(message, code, status, details);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Sleep utility for retry logic
|
|
189
|
+
*/
|
|
190
|
+
function sleep(ms) {
|
|
191
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Calculate retry delay with exponential backoff and jitter
|
|
195
|
+
*/
|
|
196
|
+
function calculateRetryDelay(attempt, baseDelay = 1000, backoff = 'exponential', maxDelay = 30000) {
|
|
197
|
+
let delay;
|
|
198
|
+
if (backoff === 'exponential') {
|
|
199
|
+
delay = baseDelay * Math.pow(2, attempt);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
delay = baseDelay * (attempt + 1);
|
|
203
|
+
}
|
|
204
|
+
// Add jitter (±20%) to prevent thundering herd
|
|
205
|
+
const jitter = delay * 0.2 * (Math.random() * 2 - 1);
|
|
206
|
+
delay = Math.min(delay + jitter, maxDelay);
|
|
207
|
+
return Math.round(delay);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check if an error is retryable based on status code
|
|
211
|
+
*/
|
|
212
|
+
function isRetryableError(statusCode) {
|
|
213
|
+
if (!statusCode)
|
|
214
|
+
return true; // Network errors are retryable
|
|
215
|
+
// Retry on server errors and rate limits
|
|
216
|
+
return statusCode >= 500 || statusCode === 429 || statusCode === 408;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Core Memory Client - Pure Browser-Safe Implementation
|
|
221
|
+
*
|
|
222
|
+
* NO Node.js dependencies, NO CLI code, NO child_process
|
|
223
|
+
* Works in: Browser, React Native, Cloudflare Workers, Edge Functions, Deno, Bun
|
|
224
|
+
*
|
|
225
|
+
* Bundle size: ~15KB gzipped
|
|
226
|
+
*/
|
|
227
|
+
/**
|
|
228
|
+
* Helper to check if response has error
|
|
229
|
+
*/
|
|
230
|
+
function hasError(response) {
|
|
231
|
+
return response.error !== undefined;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Helper to check if response has data
|
|
235
|
+
*/
|
|
236
|
+
function hasData(response) {
|
|
237
|
+
return response.data !== undefined;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Core Memory Client class for interacting with the Memory as a Service API
|
|
241
|
+
*
|
|
242
|
+
* This is a pure browser-safe client with zero Node.js dependencies.
|
|
243
|
+
* It uses only standard web APIs (fetch, AbortController, etc.)
|
|
244
|
+
*/
|
|
245
|
+
class CoreMemoryClient {
|
|
246
|
+
constructor(config) {
|
|
247
|
+
this.config = {
|
|
248
|
+
timeout: 30000,
|
|
249
|
+
...config
|
|
250
|
+
};
|
|
251
|
+
this.baseHeaders = {
|
|
252
|
+
'Content-Type': 'application/json',
|
|
253
|
+
'User-Agent': '@lanonasis/memory-client/2.0.0',
|
|
254
|
+
'X-Project-Scope': 'lanonasis-maas', // Required by backend auth middleware
|
|
255
|
+
...config.headers
|
|
256
|
+
};
|
|
257
|
+
// Set authentication headers
|
|
258
|
+
if (config.authToken) {
|
|
259
|
+
this.baseHeaders['Authorization'] = `Bearer ${config.authToken}`;
|
|
260
|
+
}
|
|
261
|
+
else if (config.apiKey) {
|
|
262
|
+
this.baseHeaders['X-API-Key'] = config.apiKey;
|
|
263
|
+
}
|
|
264
|
+
// Add organization ID header if provided
|
|
265
|
+
if (config.organizationId) {
|
|
266
|
+
this.baseHeaders['X-Organization-ID'] = config.organizationId;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Enrich request body with organization context if configured
|
|
271
|
+
* This ensures the API has the organization_id even if not in auth token
|
|
272
|
+
*/
|
|
273
|
+
enrichWithOrgContext(body) {
|
|
274
|
+
// If organizationId is configured, include it in the request body
|
|
275
|
+
if (this.config.organizationId && !body.organization_id) {
|
|
276
|
+
return {
|
|
277
|
+
...body,
|
|
278
|
+
organization_id: this.config.organizationId
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// Fallback to userId if no organizationId configured
|
|
282
|
+
if (!this.config.organizationId && this.config.userId && !body.organization_id) {
|
|
283
|
+
return {
|
|
284
|
+
...body,
|
|
285
|
+
organization_id: this.config.userId
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
return body;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Make an HTTP request to the API with retry support
|
|
292
|
+
*/
|
|
293
|
+
async request(endpoint, options = {}) {
|
|
294
|
+
const startTime = Date.now();
|
|
295
|
+
const maxRetries = this.config.retry?.maxRetries ?? 3;
|
|
296
|
+
const baseDelay = this.config.retry?.retryDelay ?? 1000;
|
|
297
|
+
const backoff = this.config.retry?.backoff ?? 'exponential';
|
|
298
|
+
// Call onRequest hook if provided
|
|
299
|
+
if (this.config.onRequest) {
|
|
300
|
+
try {
|
|
301
|
+
this.config.onRequest(endpoint);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
console.warn('onRequest hook error:', error);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Handle gateway vs direct API URL formatting
|
|
308
|
+
const baseUrl = this.config.apiUrl.includes('/api')
|
|
309
|
+
? this.config.apiUrl.replace('/api', '')
|
|
310
|
+
: this.config.apiUrl;
|
|
311
|
+
const url = `${baseUrl}/api/v1${endpoint}`;
|
|
312
|
+
let lastError;
|
|
313
|
+
let attempt = 0;
|
|
314
|
+
while (attempt <= maxRetries) {
|
|
315
|
+
try {
|
|
316
|
+
const controller = new AbortController();
|
|
317
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
318
|
+
const response = await fetch(url, {
|
|
319
|
+
headers: { ...this.baseHeaders, ...options.headers },
|
|
320
|
+
signal: controller.signal,
|
|
321
|
+
...options,
|
|
322
|
+
});
|
|
323
|
+
clearTimeout(timeoutId);
|
|
324
|
+
let data;
|
|
325
|
+
const contentType = response.headers.get('content-type');
|
|
326
|
+
if (contentType && contentType.includes('application/json')) {
|
|
327
|
+
data = await response.json();
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
data = await response.text();
|
|
331
|
+
}
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
const error = createErrorFromResponse(response.status, response.statusText, data);
|
|
334
|
+
// Only retry on retryable errors (5xx, 429, 408)
|
|
335
|
+
if (isRetryableError(response.status) && attempt < maxRetries) {
|
|
336
|
+
lastError = error;
|
|
337
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
338
|
+
await sleep(delay);
|
|
339
|
+
attempt++;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
// Call onError hook if provided
|
|
343
|
+
if (this.config.onError) {
|
|
344
|
+
try {
|
|
345
|
+
this.config.onError(error);
|
|
346
|
+
}
|
|
347
|
+
catch (hookError) {
|
|
348
|
+
console.warn('onError hook error:', hookError);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return { error, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
352
|
+
}
|
|
353
|
+
// Call onResponse hook if provided
|
|
354
|
+
if (this.config.onResponse) {
|
|
355
|
+
try {
|
|
356
|
+
const duration = Date.now() - startTime;
|
|
357
|
+
this.config.onResponse(endpoint, duration);
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
console.warn('onResponse hook error:', error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return { data, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
367
|
+
const timeoutError = createErrorResponse('Request timeout', 'TIMEOUT_ERROR', 408);
|
|
368
|
+
// Retry on timeout
|
|
369
|
+
if (attempt < maxRetries) {
|
|
370
|
+
lastError = timeoutError;
|
|
371
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
372
|
+
await sleep(delay);
|
|
373
|
+
attempt++;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (this.config.onError) {
|
|
377
|
+
try {
|
|
378
|
+
this.config.onError(timeoutError);
|
|
379
|
+
}
|
|
380
|
+
catch (hookError) {
|
|
381
|
+
console.warn('onError hook error:', hookError);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return { error: timeoutError, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
385
|
+
}
|
|
386
|
+
const networkError = createErrorResponse(error instanceof Error ? error.message : 'Network error', 'NETWORK_ERROR');
|
|
387
|
+
// Retry on network errors
|
|
388
|
+
if (attempt < maxRetries) {
|
|
389
|
+
lastError = networkError;
|
|
390
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
391
|
+
await sleep(delay);
|
|
392
|
+
attempt++;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (this.config.onError) {
|
|
396
|
+
try {
|
|
397
|
+
this.config.onError(networkError);
|
|
398
|
+
}
|
|
399
|
+
catch (hookError) {
|
|
400
|
+
console.warn('onError hook error:', hookError);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return { error: networkError, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Should never reach here, but handle it gracefully
|
|
407
|
+
return {
|
|
408
|
+
error: lastError ?? createErrorResponse('Max retries exceeded', 'API_ERROR'),
|
|
409
|
+
meta: { duration: Date.now() - startTime, retries: attempt }
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Validate input using Zod schema and return validation error if invalid
|
|
414
|
+
*/
|
|
415
|
+
validateInput(schema, data) {
|
|
416
|
+
const result = schema.safeParse(data);
|
|
417
|
+
if (!result.success) {
|
|
418
|
+
// Extract error details from Zod error
|
|
419
|
+
const zodError = result.error;
|
|
420
|
+
const details = zodError?.issues?.map(issue => ({
|
|
421
|
+
field: issue.path.map(String).join('.'),
|
|
422
|
+
message: issue.message
|
|
423
|
+
})) ?? [];
|
|
424
|
+
return {
|
|
425
|
+
error: createErrorResponse('Validation failed', 'VALIDATION_ERROR', 400, details)
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Test the API connection and authentication
|
|
432
|
+
*/
|
|
433
|
+
async healthCheck() {
|
|
434
|
+
return this.request('/health');
|
|
435
|
+
}
|
|
436
|
+
// Memory Operations
|
|
437
|
+
/**
|
|
438
|
+
* Create a new memory with validation
|
|
439
|
+
*/
|
|
440
|
+
async createMemory(memory) {
|
|
441
|
+
// Validate input before making request
|
|
442
|
+
const validationError = this.validateInput(createMemorySchema, memory);
|
|
443
|
+
if (validationError) {
|
|
444
|
+
return { error: validationError.error };
|
|
445
|
+
}
|
|
446
|
+
const enrichedMemory = this.enrichWithOrgContext(memory);
|
|
447
|
+
return this.request('/memory', {
|
|
448
|
+
method: 'POST',
|
|
449
|
+
body: JSON.stringify(enrichedMemory)
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get a memory by ID
|
|
454
|
+
*/
|
|
455
|
+
async getMemory(id) {
|
|
456
|
+
return this.request(`/memory/${encodeURIComponent(id)}`);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Update an existing memory with validation
|
|
460
|
+
*/
|
|
461
|
+
async updateMemory(id, updates) {
|
|
462
|
+
// Validate input before making request
|
|
463
|
+
const validationError = this.validateInput(updateMemorySchema, updates);
|
|
464
|
+
if (validationError) {
|
|
465
|
+
return { error: validationError.error };
|
|
466
|
+
}
|
|
467
|
+
return this.request(`/memory/${encodeURIComponent(id)}`, {
|
|
468
|
+
method: 'PUT',
|
|
469
|
+
body: JSON.stringify(updates)
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Delete a memory
|
|
474
|
+
*/
|
|
475
|
+
async deleteMemory(id) {
|
|
476
|
+
return this.request(`/memory/${encodeURIComponent(id)}`, {
|
|
477
|
+
method: 'DELETE'
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* List memories with optional filtering and pagination
|
|
482
|
+
*/
|
|
483
|
+
async listMemories(options = {}) {
|
|
484
|
+
const params = new URLSearchParams();
|
|
485
|
+
Object.entries(options).forEach(([key, value]) => {
|
|
486
|
+
if (value !== undefined && value !== null) {
|
|
487
|
+
if (Array.isArray(value)) {
|
|
488
|
+
params.append(key, value.join(','));
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
params.append(key, String(value));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
const queryString = params.toString();
|
|
496
|
+
const endpoint = queryString ? `/memory?${queryString}` : '/memory';
|
|
497
|
+
return this.request(endpoint);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Search memories using semantic search with validation
|
|
501
|
+
*/
|
|
502
|
+
async searchMemories(request) {
|
|
503
|
+
// Validate input before making request
|
|
504
|
+
const validationError = this.validateInput(searchMemorySchema, request);
|
|
505
|
+
if (validationError) {
|
|
506
|
+
// Return error response (data will be undefined, only error is set)
|
|
507
|
+
return { error: validationError.error };
|
|
508
|
+
}
|
|
509
|
+
const enrichedRequest = this.enrichWithOrgContext(request);
|
|
510
|
+
return this.request('/memory/search', {
|
|
511
|
+
method: 'POST',
|
|
512
|
+
body: JSON.stringify(enrichedRequest)
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Bulk delete multiple memories
|
|
517
|
+
*/
|
|
518
|
+
async bulkDeleteMemories(memoryIds) {
|
|
519
|
+
const enrichedRequest = this.enrichWithOrgContext({ memory_ids: memoryIds });
|
|
520
|
+
return this.request('/memory/bulk/delete', {
|
|
521
|
+
method: 'POST',
|
|
522
|
+
body: JSON.stringify(enrichedRequest)
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// Topic Operations
|
|
526
|
+
/**
|
|
527
|
+
* Create a new topic with validation
|
|
528
|
+
*/
|
|
529
|
+
async createTopic(topic) {
|
|
530
|
+
// Validate input before making request
|
|
531
|
+
const validationError = this.validateInput(createTopicSchema, topic);
|
|
532
|
+
if (validationError) {
|
|
533
|
+
return { error: validationError.error };
|
|
534
|
+
}
|
|
535
|
+
const enrichedTopic = this.enrichWithOrgContext(topic);
|
|
536
|
+
return this.request('/topics', {
|
|
537
|
+
method: 'POST',
|
|
538
|
+
body: JSON.stringify(enrichedTopic)
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Get all topics
|
|
543
|
+
*/
|
|
544
|
+
async getTopics() {
|
|
545
|
+
return this.request('/topics');
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Get a topic by ID
|
|
549
|
+
*/
|
|
550
|
+
async getTopic(id) {
|
|
551
|
+
return this.request(`/topics/${encodeURIComponent(id)}`);
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Update a topic
|
|
555
|
+
*/
|
|
556
|
+
async updateTopic(id, updates) {
|
|
557
|
+
return this.request(`/topics/${encodeURIComponent(id)}`, {
|
|
558
|
+
method: 'PUT',
|
|
559
|
+
body: JSON.stringify(updates)
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Delete a topic
|
|
564
|
+
*/
|
|
565
|
+
async deleteTopic(id) {
|
|
566
|
+
return this.request(`/topics/${encodeURIComponent(id)}`, {
|
|
567
|
+
method: 'DELETE'
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Get user memory statistics
|
|
572
|
+
*/
|
|
573
|
+
async getMemoryStats() {
|
|
574
|
+
return this.request('/memory/stats');
|
|
575
|
+
}
|
|
576
|
+
// ========================================
|
|
577
|
+
// Intelligence Features (v2.0)
|
|
578
|
+
// ========================================
|
|
579
|
+
/**
|
|
580
|
+
* Create a memory with preprocessing options (chunking, intelligence extraction)
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```typescript
|
|
584
|
+
* const result = await client.createMemoryWithPreprocessing({
|
|
585
|
+
* title: 'Auth System Docs',
|
|
586
|
+
* content: 'Long content...',
|
|
587
|
+
* memory_type: 'knowledge',
|
|
588
|
+
* preprocessing: {
|
|
589
|
+
* chunking: { strategy: 'semantic', maxChunkSize: 1000 },
|
|
590
|
+
* extractMetadata: true
|
|
591
|
+
* }
|
|
592
|
+
* });
|
|
593
|
+
* ```
|
|
594
|
+
*/
|
|
595
|
+
async createMemoryWithPreprocessing(memory) {
|
|
596
|
+
// Validate base memory fields
|
|
597
|
+
const validationError = this.validateInput(createMemorySchema, memory);
|
|
598
|
+
if (validationError) {
|
|
599
|
+
return { error: validationError.error };
|
|
600
|
+
}
|
|
601
|
+
const enrichedMemory = this.enrichWithOrgContext(memory);
|
|
602
|
+
return this.request('/memory', {
|
|
603
|
+
method: 'POST',
|
|
604
|
+
body: JSON.stringify(enrichedMemory)
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Update a memory with re-chunking and embedding regeneration
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```typescript
|
|
612
|
+
* const result = await client.updateMemoryWithPreprocessing('mem_123', {
|
|
613
|
+
* content: 'Updated content...',
|
|
614
|
+
* rechunk: true,
|
|
615
|
+
* regenerate_embedding: true
|
|
616
|
+
* });
|
|
617
|
+
* ```
|
|
618
|
+
*/
|
|
619
|
+
async updateMemoryWithPreprocessing(id, updates) {
|
|
620
|
+
const validationError = this.validateInput(updateMemorySchema, updates);
|
|
621
|
+
if (validationError) {
|
|
622
|
+
return { error: validationError.error };
|
|
623
|
+
}
|
|
624
|
+
return this.request(`/memory/${encodeURIComponent(id)}`, {
|
|
625
|
+
method: 'PUT',
|
|
626
|
+
body: JSON.stringify(updates)
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Enhanced semantic search with hybrid mode (vector + text)
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* ```typescript
|
|
634
|
+
* const result = await client.enhancedSearch({
|
|
635
|
+
* query: 'authentication flow',
|
|
636
|
+
* search_mode: 'hybrid',
|
|
637
|
+
* filters: { tags: ['auth'], project_id: 'proj_123' },
|
|
638
|
+
* include_chunks: true
|
|
639
|
+
* });
|
|
640
|
+
* ```
|
|
641
|
+
*/
|
|
642
|
+
async enhancedSearch(request) {
|
|
643
|
+
const validationError = this.validateInput(enhancedSearchSchema, request);
|
|
644
|
+
if (validationError) {
|
|
645
|
+
return { error: validationError.error };
|
|
646
|
+
}
|
|
647
|
+
const enrichedRequest = this.enrichWithOrgContext(request);
|
|
648
|
+
return this.request('/memory/search', {
|
|
649
|
+
method: 'POST',
|
|
650
|
+
body: JSON.stringify(enrichedRequest)
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
// ========================================
|
|
654
|
+
// Analytics Operations
|
|
655
|
+
// ========================================
|
|
656
|
+
/**
|
|
657
|
+
* Get search analytics data
|
|
658
|
+
*
|
|
659
|
+
* @example
|
|
660
|
+
* ```typescript
|
|
661
|
+
* const analytics = await client.getSearchAnalytics({
|
|
662
|
+
* from: '2025-01-01',
|
|
663
|
+
* to: '2025-12-31',
|
|
664
|
+
* group_by: 'day'
|
|
665
|
+
* });
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
async getSearchAnalytics(options = {}) {
|
|
669
|
+
const validationError = this.validateInput(analyticsDateRangeSchema, options);
|
|
670
|
+
if (validationError) {
|
|
671
|
+
return { error: validationError.error };
|
|
672
|
+
}
|
|
673
|
+
const params = new URLSearchParams();
|
|
674
|
+
if (options.from)
|
|
675
|
+
params.append('from', options.from);
|
|
676
|
+
if (options.to)
|
|
677
|
+
params.append('to', options.to);
|
|
678
|
+
if (options.group_by)
|
|
679
|
+
params.append('group_by', options.group_by);
|
|
680
|
+
const queryString = params.toString();
|
|
681
|
+
const endpoint = queryString ? `/analytics/search?${queryString}` : '/analytics/search';
|
|
682
|
+
return this.request(endpoint);
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Get memory access patterns
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* ```typescript
|
|
689
|
+
* const patterns = await client.getAccessPatterns({
|
|
690
|
+
* from: '2025-01-01',
|
|
691
|
+
* to: '2025-12-31'
|
|
692
|
+
* });
|
|
693
|
+
* console.log(patterns.data?.most_accessed);
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
async getAccessPatterns(options = {}) {
|
|
697
|
+
const params = new URLSearchParams();
|
|
698
|
+
if (options.from)
|
|
699
|
+
params.append('from', options.from);
|
|
700
|
+
if (options.to)
|
|
701
|
+
params.append('to', options.to);
|
|
702
|
+
const queryString = params.toString();
|
|
703
|
+
const endpoint = queryString ? `/analytics/access?${queryString}` : '/analytics/access';
|
|
704
|
+
return this.request(endpoint);
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Get extended memory statistics with storage and activity metrics
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* const stats = await client.getExtendedStats();
|
|
712
|
+
* console.log(`Total chunks: ${stats.data?.storage.total_chunks}`);
|
|
713
|
+
* console.log(`Created today: ${stats.data?.activity.created_today}`);
|
|
714
|
+
* ```
|
|
715
|
+
*/
|
|
716
|
+
async getExtendedStats() {
|
|
717
|
+
return this.request('/analytics/stats');
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Get topic with its memories
|
|
721
|
+
*
|
|
722
|
+
* @example
|
|
723
|
+
* ```typescript
|
|
724
|
+
* const topic = await client.getTopicWithMemories('topic_123');
|
|
725
|
+
* console.log(topic.data?.memories);
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
async getTopicWithMemories(topicId, options = {}) {
|
|
729
|
+
const params = new URLSearchParams();
|
|
730
|
+
if (options.limit)
|
|
731
|
+
params.append('limit', String(options.limit));
|
|
732
|
+
if (options.offset)
|
|
733
|
+
params.append('offset', String(options.offset));
|
|
734
|
+
const queryString = params.toString();
|
|
735
|
+
const endpoint = queryString
|
|
736
|
+
? `/topics/${encodeURIComponent(topicId)}/memories?${queryString}`
|
|
737
|
+
: `/topics/${encodeURIComponent(topicId)}/memories`;
|
|
738
|
+
return this.request(endpoint);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Get topics in hierarchical structure
|
|
742
|
+
*
|
|
743
|
+
* @example
|
|
744
|
+
* ```typescript
|
|
745
|
+
* const topics = await client.getTopicsHierarchy();
|
|
746
|
+
* // Returns nested topic tree with children
|
|
747
|
+
* ```
|
|
748
|
+
*/
|
|
749
|
+
async getTopicsHierarchy() {
|
|
750
|
+
return this.request('/topics?include_hierarchy=true');
|
|
751
|
+
}
|
|
752
|
+
// Utility Methods
|
|
753
|
+
/**
|
|
754
|
+
* Update authentication token
|
|
755
|
+
*/
|
|
756
|
+
setAuthToken(token) {
|
|
757
|
+
this.baseHeaders['Authorization'] = `Bearer ${token}`;
|
|
758
|
+
delete this.baseHeaders['X-API-Key'];
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Update API key
|
|
762
|
+
*/
|
|
763
|
+
setApiKey(apiKey) {
|
|
764
|
+
this.baseHeaders['X-API-Key'] = apiKey;
|
|
765
|
+
delete this.baseHeaders['Authorization'];
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Clear authentication
|
|
769
|
+
*/
|
|
770
|
+
clearAuth() {
|
|
771
|
+
delete this.baseHeaders['Authorization'];
|
|
772
|
+
delete this.baseHeaders['X-API-Key'];
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Update configuration
|
|
776
|
+
*/
|
|
777
|
+
updateConfig(updates) {
|
|
778
|
+
this.config = { ...this.config, ...updates };
|
|
779
|
+
if (updates.headers) {
|
|
780
|
+
this.baseHeaders = { ...this.baseHeaders, ...updates.headers };
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Get current configuration (excluding sensitive data)
|
|
785
|
+
*/
|
|
786
|
+
getConfig() {
|
|
787
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
788
|
+
const { apiKey, authToken, ...safeConfig } = this.config;
|
|
789
|
+
return safeConfig;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Factory function to create a new Core Memory Client instance
|
|
794
|
+
*/
|
|
795
|
+
function createMemoryClient(config) {
|
|
796
|
+
return new CoreMemoryClient(config);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Error handling for Memory Client
|
|
801
|
+
* Browser-safe, no Node.js dependencies
|
|
802
|
+
*/
|
|
803
|
+
/**
|
|
804
|
+
* Standardized error codes for programmatic error handling
|
|
805
|
+
*/
|
|
806
|
+
const ERROR_CODES = [
|
|
807
|
+
'API_ERROR',
|
|
808
|
+
'AUTH_ERROR',
|
|
809
|
+
'VALIDATION_ERROR',
|
|
810
|
+
'TIMEOUT_ERROR',
|
|
811
|
+
'RATE_LIMIT_ERROR',
|
|
812
|
+
'NOT_FOUND',
|
|
813
|
+
'NETWORK_ERROR',
|
|
814
|
+
'FORBIDDEN',
|
|
815
|
+
'CONFLICT',
|
|
816
|
+
'SERVER_ERROR'
|
|
817
|
+
];
|
|
818
|
+
/**
|
|
819
|
+
* Type guard to check if an object is an ApiErrorResponse
|
|
820
|
+
*/
|
|
821
|
+
function isApiErrorResponse(value) {
|
|
822
|
+
return (typeof value === 'object' &&
|
|
823
|
+
value !== null &&
|
|
824
|
+
'code' in value &&
|
|
825
|
+
'message' in value &&
|
|
826
|
+
typeof value.code === 'string' &&
|
|
827
|
+
typeof value.message === 'string');
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Base error class for Memory Client errors
|
|
831
|
+
*/
|
|
832
|
+
class MemoryClientError extends Error {
|
|
833
|
+
constructor(message, code = 'API_ERROR', statusCode, details) {
|
|
834
|
+
super(message);
|
|
835
|
+
this.code = code;
|
|
836
|
+
this.statusCode = statusCode;
|
|
837
|
+
this.details = details;
|
|
838
|
+
this.name = 'MemoryClientError';
|
|
839
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
840
|
+
if (Error.captureStackTrace) {
|
|
841
|
+
Error.captureStackTrace(this, MemoryClientError);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Convert to ApiErrorResponse for consistent API responses
|
|
846
|
+
*/
|
|
847
|
+
toResponse() {
|
|
848
|
+
return {
|
|
849
|
+
code: this.code,
|
|
850
|
+
message: this.message,
|
|
851
|
+
statusCode: this.statusCode,
|
|
852
|
+
details: this.details,
|
|
853
|
+
timestamp: new Date().toISOString()
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Network/API error
|
|
859
|
+
*/
|
|
860
|
+
class ApiError extends MemoryClientError {
|
|
861
|
+
constructor(message, statusCode, details) {
|
|
862
|
+
super(message, 'API_ERROR', statusCode, details);
|
|
863
|
+
this.name = 'ApiError';
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Create from an HTTP response
|
|
867
|
+
*/
|
|
868
|
+
static fromResponse(status, statusText, body) {
|
|
869
|
+
let message = `HTTP ${status}: ${statusText}`;
|
|
870
|
+
let details = undefined;
|
|
871
|
+
if (body && typeof body === 'object') {
|
|
872
|
+
const bodyObj = body;
|
|
873
|
+
if (typeof bodyObj.error === 'string') {
|
|
874
|
+
message = bodyObj.error;
|
|
875
|
+
}
|
|
876
|
+
else if (typeof bodyObj.message === 'string') {
|
|
877
|
+
message = bodyObj.message;
|
|
878
|
+
}
|
|
879
|
+
if (bodyObj.details) {
|
|
880
|
+
details = bodyObj.details;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return new ApiError(message, status, details);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Authentication error
|
|
888
|
+
*/
|
|
889
|
+
class AuthenticationError extends MemoryClientError {
|
|
890
|
+
constructor(message = 'Authentication required') {
|
|
891
|
+
super(message, 'AUTH_ERROR', 401);
|
|
892
|
+
this.name = 'AuthenticationError';
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Validation error with field-level details
|
|
897
|
+
*/
|
|
898
|
+
class ValidationError extends MemoryClientError {
|
|
899
|
+
constructor(message, details) {
|
|
900
|
+
super(message, 'VALIDATION_ERROR', 400, details);
|
|
901
|
+
this.name = 'ValidationError';
|
|
902
|
+
// Parse validation details into field errors
|
|
903
|
+
this.validationErrors = [];
|
|
904
|
+
if (Array.isArray(details)) {
|
|
905
|
+
this.validationErrors = details.filter((item) => typeof item === 'object' &&
|
|
906
|
+
item !== null &&
|
|
907
|
+
typeof item.field === 'string' &&
|
|
908
|
+
typeof item.message === 'string');
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Create from Zod error
|
|
913
|
+
*/
|
|
914
|
+
static fromZodError(error) {
|
|
915
|
+
const details = error.issues.map(issue => ({
|
|
916
|
+
field: issue.path.join('.'),
|
|
917
|
+
message: issue.message
|
|
918
|
+
}));
|
|
919
|
+
return new ValidationError('Validation failed', details);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Timeout error
|
|
924
|
+
*/
|
|
925
|
+
class TimeoutError extends MemoryClientError {
|
|
926
|
+
constructor(message = 'Request timeout') {
|
|
927
|
+
super(message, 'TIMEOUT_ERROR', 408);
|
|
928
|
+
this.name = 'TimeoutError';
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Rate limit error with retry-after info
|
|
933
|
+
*/
|
|
934
|
+
class RateLimitError extends MemoryClientError {
|
|
935
|
+
constructor(message = 'Rate limit exceeded', retryAfter) {
|
|
936
|
+
super(message, 'RATE_LIMIT_ERROR', 429, { retryAfter });
|
|
937
|
+
this.name = 'RateLimitError';
|
|
938
|
+
this.retryAfter = retryAfter;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Not found error
|
|
943
|
+
*/
|
|
944
|
+
class NotFoundError extends MemoryClientError {
|
|
945
|
+
constructor(resource) {
|
|
946
|
+
super(`${resource} not found`, 'NOT_FOUND', 404);
|
|
947
|
+
this.name = 'NotFoundError';
|
|
948
|
+
this.resource = resource;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Network error (no response received)
|
|
953
|
+
*/
|
|
954
|
+
class NetworkError extends MemoryClientError {
|
|
955
|
+
constructor(message = 'Network error') {
|
|
956
|
+
super(message, 'NETWORK_ERROR');
|
|
957
|
+
this.name = 'NetworkError';
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Server error (5xx responses)
|
|
962
|
+
*/
|
|
963
|
+
class ServerError extends MemoryClientError {
|
|
964
|
+
constructor(message, statusCode = 500) {
|
|
965
|
+
super(message, 'SERVER_ERROR', statusCode);
|
|
966
|
+
this.name = 'ServerError';
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Create appropriate error class from status code
|
|
971
|
+
*/
|
|
972
|
+
function createErrorFromStatus(status, message, details) {
|
|
973
|
+
switch (status) {
|
|
974
|
+
case 400:
|
|
975
|
+
return new ValidationError(message, details);
|
|
976
|
+
case 401:
|
|
977
|
+
return new AuthenticationError(message);
|
|
978
|
+
case 404:
|
|
979
|
+
return new NotFoundError(message);
|
|
980
|
+
case 408:
|
|
981
|
+
return new TimeoutError(message);
|
|
982
|
+
case 429:
|
|
983
|
+
return new RateLimitError(message);
|
|
984
|
+
case 500:
|
|
985
|
+
case 502:
|
|
986
|
+
case 503:
|
|
987
|
+
case 504:
|
|
988
|
+
return new ServerError(message, status);
|
|
989
|
+
default:
|
|
990
|
+
return new ApiError(message, status, details);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* @lanonasis/memory-client/core
|
|
996
|
+
*
|
|
997
|
+
* Pure browser-safe Memory Client
|
|
998
|
+
* NO Node.js dependencies, NO CLI code, NO child_process
|
|
999
|
+
* Works in: Browser, React Native, Cloudflare Workers, Edge Functions, Deno, Bun
|
|
1000
|
+
*
|
|
1001
|
+
* Bundle size: ~15KB gzipped
|
|
1002
|
+
*/
|
|
1003
|
+
// Client
|
|
1004
|
+
// Constants
|
|
1005
|
+
const VERSION = '2.0.0';
|
|
1006
|
+
const CLIENT_NAME = '@lanonasis/memory-client';
|
|
1007
|
+
// Environment detection (browser-safe)
|
|
1008
|
+
const isBrowser = typeof window !== 'undefined';
|
|
1009
|
+
const isNode = typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node;
|
|
1010
|
+
// Default configurations for different environments
|
|
1011
|
+
const defaultConfigs = {
|
|
1012
|
+
development: {
|
|
1013
|
+
apiUrl: 'http://localhost:3001',
|
|
1014
|
+
timeout: 30000,
|
|
1015
|
+
},
|
|
1016
|
+
production: {
|
|
1017
|
+
apiUrl: 'https://api.lanonasis.com',
|
|
1018
|
+
timeout: 15000,
|
|
1019
|
+
},
|
|
1020
|
+
edge: {
|
|
1021
|
+
apiUrl: 'https://api.lanonasis.com',
|
|
1022
|
+
timeout: 5000, // Lower timeout for edge environments
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
export { ApiError, AuthenticationError, CHUNKING_STRATEGIES, CLIENT_NAME, CONTENT_TYPES, CoreMemoryClient, ERROR_CODES, MEMORY_STATUSES, MEMORY_TYPES, MemoryClientError, NetworkError, NotFoundError, RateLimitError, SEARCH_MODES, ServerError, TimeoutError, VERSION, ValidationError, analyticsDateRangeSchema, calculateRetryDelay, createErrorFromStatus, createErrorResponse, createMemoryClient, createMemorySchema, createTopicSchema, defaultConfigs, enhancedSearchSchema, hasData, hasError, httpStatusToErrorCode, isApiErrorResponse, isBrowser, isNode, isRetryableError, preprocessingOptionsSchema, safeJsonParse, searchMemorySchema, updateMemorySchema };
|
|
1027
|
+
//# sourceMappingURL=index.js.map
|