@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
package/dist/index.js
CHANGED
|
@@ -1,22 +1,261 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zod = require('zod');
|
|
3
4
|
var child_process = require('child_process');
|
|
4
5
|
var util = require('util');
|
|
5
|
-
var zod = require('zod');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Memory
|
|
8
|
+
* Memory types supported by the service
|
|
9
|
+
*/
|
|
10
|
+
const MEMORY_TYPES = ['context', 'project', 'knowledge', 'reference', 'personal', 'workflow'];
|
|
11
|
+
/**
|
|
12
|
+
* Memory status values
|
|
13
|
+
*/
|
|
14
|
+
const MEMORY_STATUSES = ['active', 'archived', 'draft', 'deleted'];
|
|
15
|
+
/**
|
|
16
|
+
* Validation schemas using Zod
|
|
17
|
+
*/
|
|
18
|
+
const createMemorySchema = zod.z.object({
|
|
19
|
+
title: zod.z.string().min(1).max(500),
|
|
20
|
+
content: zod.z.string().min(1).max(50000),
|
|
21
|
+
summary: zod.z.string().max(1000).optional(),
|
|
22
|
+
memory_type: zod.z.enum(MEMORY_TYPES).default('context'),
|
|
23
|
+
topic_id: zod.z.string().uuid().optional(),
|
|
24
|
+
project_ref: zod.z.string().max(100).optional(),
|
|
25
|
+
tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).default([]),
|
|
26
|
+
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
27
|
+
});
|
|
28
|
+
const updateMemorySchema = zod.z.object({
|
|
29
|
+
title: zod.z.string().min(1).max(500).optional(),
|
|
30
|
+
content: zod.z.string().min(1).max(50000).optional(),
|
|
31
|
+
summary: zod.z.string().max(1000).optional(),
|
|
32
|
+
memory_type: zod.z.enum(MEMORY_TYPES).optional(),
|
|
33
|
+
status: zod.z.enum(MEMORY_STATUSES).optional(),
|
|
34
|
+
topic_id: zod.z.string().uuid().nullable().optional(),
|
|
35
|
+
project_ref: zod.z.string().max(100).nullable().optional(),
|
|
36
|
+
tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).optional(),
|
|
37
|
+
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
38
|
+
});
|
|
39
|
+
const searchMemorySchema = zod.z.object({
|
|
40
|
+
query: zod.z.string().min(1).max(1000),
|
|
41
|
+
memory_types: zod.z.array(zod.z.enum(MEMORY_TYPES)).optional(),
|
|
42
|
+
tags: zod.z.array(zod.z.string()).optional(),
|
|
43
|
+
topic_id: zod.z.string().uuid().optional(),
|
|
44
|
+
project_ref: zod.z.string().optional(),
|
|
45
|
+
status: zod.z.enum(MEMORY_STATUSES).default('active'),
|
|
46
|
+
limit: zod.z.number().int().min(1).max(100).default(20),
|
|
47
|
+
threshold: zod.z.number().min(0).max(1).default(0.7)
|
|
48
|
+
});
|
|
49
|
+
const createTopicSchema = zod.z.object({
|
|
50
|
+
name: zod.z.string().min(1).max(100),
|
|
51
|
+
description: zod.z.string().max(500).optional(),
|
|
52
|
+
color: zod.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
53
|
+
icon: zod.z.string().max(50).optional(),
|
|
54
|
+
parent_topic_id: zod.z.string().uuid().optional()
|
|
55
|
+
});
|
|
56
|
+
// ========================================
|
|
57
|
+
// Intelligence Feature Types (v2.0)
|
|
58
|
+
// ========================================
|
|
59
|
+
/**
|
|
60
|
+
* Chunking strategies for content preprocessing
|
|
61
|
+
*/
|
|
62
|
+
const CHUNKING_STRATEGIES = ['semantic', 'fixed-size', 'paragraph', 'sentence', 'code-block'];
|
|
63
|
+
/**
|
|
64
|
+
* Content types detected or specified
|
|
65
|
+
*/
|
|
66
|
+
const CONTENT_TYPES = ['text', 'code', 'markdown', 'json', 'yaml'];
|
|
67
|
+
// ========================================
|
|
68
|
+
// Enhanced Search Types
|
|
69
|
+
// ========================================
|
|
70
|
+
/**
|
|
71
|
+
* Search modes for memory queries
|
|
72
|
+
*/
|
|
73
|
+
const SEARCH_MODES = ['vector', 'text', 'hybrid'];
|
|
74
|
+
// ========================================
|
|
75
|
+
// Validation Schemas for Intelligence
|
|
76
|
+
// ========================================
|
|
77
|
+
const preprocessingOptionsSchema = zod.z.object({
|
|
78
|
+
chunking: zod.z.object({
|
|
79
|
+
strategy: zod.z.enum(CHUNKING_STRATEGIES).optional(),
|
|
80
|
+
maxChunkSize: zod.z.number().int().min(100).max(10000).optional(),
|
|
81
|
+
overlap: zod.z.number().int().min(0).max(500).optional()
|
|
82
|
+
}).optional(),
|
|
83
|
+
cleanContent: zod.z.boolean().optional(),
|
|
84
|
+
extractMetadata: zod.z.boolean().optional()
|
|
85
|
+
}).optional();
|
|
86
|
+
const enhancedSearchSchema = zod.z.object({
|
|
87
|
+
query: zod.z.string().min(1).max(1000),
|
|
88
|
+
type: zod.z.enum(MEMORY_TYPES).optional(),
|
|
89
|
+
threshold: zod.z.number().min(0).max(1).default(0.7),
|
|
90
|
+
limit: zod.z.number().int().min(1).max(100).default(20),
|
|
91
|
+
search_mode: zod.z.enum(SEARCH_MODES).default('hybrid'),
|
|
92
|
+
filters: zod.z.object({
|
|
93
|
+
tags: zod.z.array(zod.z.string()).optional(),
|
|
94
|
+
project_id: zod.z.string().uuid().optional(),
|
|
95
|
+
topic_id: zod.z.string().uuid().optional(),
|
|
96
|
+
date_range: zod.z.object({
|
|
97
|
+
from: zod.z.string().optional(),
|
|
98
|
+
to: zod.z.string().optional()
|
|
99
|
+
}).optional()
|
|
100
|
+
}).optional(),
|
|
101
|
+
include_chunks: zod.z.boolean().default(false)
|
|
102
|
+
});
|
|
103
|
+
const analyticsDateRangeSchema = zod.z.object({
|
|
104
|
+
from: zod.z.string().optional(),
|
|
105
|
+
to: zod.z.string().optional(),
|
|
106
|
+
group_by: zod.z.enum(['day', 'week', 'month']).default('day')
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Core Utilities for Memory Client
|
|
111
|
+
* Browser-safe, no Node.js dependencies
|
|
112
|
+
*/
|
|
113
|
+
/**
|
|
114
|
+
* Safely parse JSON with detailed error reporting
|
|
115
|
+
* Prevents scattered try/catch blocks throughout the codebase
|
|
116
|
+
*/
|
|
117
|
+
function safeJsonParse(input) {
|
|
118
|
+
try {
|
|
119
|
+
const data = JSON.parse(input);
|
|
120
|
+
return { success: true, data };
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const message = error instanceof Error
|
|
124
|
+
? error.message
|
|
125
|
+
: 'Unknown JSON parse error';
|
|
126
|
+
return { success: false, error: `Invalid JSON: ${message}` };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* HTTP status code to error code mapping
|
|
9
131
|
*/
|
|
10
|
-
|
|
132
|
+
function httpStatusToErrorCode(status) {
|
|
133
|
+
switch (status) {
|
|
134
|
+
case 400:
|
|
135
|
+
return 'VALIDATION_ERROR';
|
|
136
|
+
case 401:
|
|
137
|
+
return 'AUTH_ERROR';
|
|
138
|
+
case 403:
|
|
139
|
+
return 'FORBIDDEN';
|
|
140
|
+
case 404:
|
|
141
|
+
return 'NOT_FOUND';
|
|
142
|
+
case 408:
|
|
143
|
+
return 'TIMEOUT_ERROR';
|
|
144
|
+
case 409:
|
|
145
|
+
return 'CONFLICT';
|
|
146
|
+
case 429:
|
|
147
|
+
return 'RATE_LIMIT_ERROR';
|
|
148
|
+
case 500:
|
|
149
|
+
case 502:
|
|
150
|
+
case 503:
|
|
151
|
+
case 504:
|
|
152
|
+
return 'SERVER_ERROR';
|
|
153
|
+
default:
|
|
154
|
+
return 'API_ERROR';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create a standardized error response from various error sources
|
|
159
|
+
*/
|
|
160
|
+
function createErrorResponse(message, code = 'API_ERROR', statusCode, details) {
|
|
161
|
+
return {
|
|
162
|
+
code,
|
|
163
|
+
message,
|
|
164
|
+
statusCode,
|
|
165
|
+
details,
|
|
166
|
+
timestamp: new Date().toISOString()
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Create an error response from an HTTP response
|
|
171
|
+
*/
|
|
172
|
+
function createErrorFromResponse(status, statusText, body) {
|
|
173
|
+
const code = httpStatusToErrorCode(status);
|
|
174
|
+
// Try to extract message from response body
|
|
175
|
+
let message = `HTTP ${status}: ${statusText}`;
|
|
176
|
+
let details = undefined;
|
|
177
|
+
if (body && typeof body === 'object') {
|
|
178
|
+
const bodyObj = body;
|
|
179
|
+
if (typeof bodyObj.error === 'string') {
|
|
180
|
+
message = bodyObj.error;
|
|
181
|
+
}
|
|
182
|
+
else if (typeof bodyObj.message === 'string') {
|
|
183
|
+
message = bodyObj.message;
|
|
184
|
+
}
|
|
185
|
+
if (bodyObj.details) {
|
|
186
|
+
details = bodyObj.details;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return createErrorResponse(message, code, status, details);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sleep utility for retry logic
|
|
193
|
+
*/
|
|
194
|
+
function sleep(ms) {
|
|
195
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Calculate retry delay with exponential backoff and jitter
|
|
199
|
+
*/
|
|
200
|
+
function calculateRetryDelay(attempt, baseDelay = 1000, backoff = 'exponential', maxDelay = 30000) {
|
|
201
|
+
let delay;
|
|
202
|
+
if (backoff === 'exponential') {
|
|
203
|
+
delay = baseDelay * Math.pow(2, attempt);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
delay = baseDelay * (attempt + 1);
|
|
207
|
+
}
|
|
208
|
+
// Add jitter (±20%) to prevent thundering herd
|
|
209
|
+
const jitter = delay * 0.2 * (Math.random() * 2 - 1);
|
|
210
|
+
delay = Math.min(delay + jitter, maxDelay);
|
|
211
|
+
return Math.round(delay);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Check if an error is retryable based on status code
|
|
215
|
+
*/
|
|
216
|
+
function isRetryableError(statusCode) {
|
|
217
|
+
if (!statusCode)
|
|
218
|
+
return true; // Network errors are retryable
|
|
219
|
+
// Retry on server errors and rate limits
|
|
220
|
+
return statusCode >= 500 || statusCode === 429 || statusCode === 408;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Core Memory Client - Pure Browser-Safe Implementation
|
|
225
|
+
*
|
|
226
|
+
* NO Node.js dependencies, NO CLI code, NO child_process
|
|
227
|
+
* Works in: Browser, React Native, Cloudflare Workers, Edge Functions, Deno, Bun
|
|
228
|
+
*
|
|
229
|
+
* Bundle size: ~15KB gzipped
|
|
230
|
+
*/
|
|
231
|
+
/**
|
|
232
|
+
* Helper to check if response has error
|
|
233
|
+
*/
|
|
234
|
+
function hasError(response) {
|
|
235
|
+
return response.error !== undefined;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Helper to check if response has data
|
|
239
|
+
*/
|
|
240
|
+
function hasData(response) {
|
|
241
|
+
return response.data !== undefined;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Core Memory Client class for interacting with the Memory as a Service API
|
|
245
|
+
*
|
|
246
|
+
* This is a pure browser-safe client with zero Node.js dependencies.
|
|
247
|
+
* It uses only standard web APIs (fetch, AbortController, etc.)
|
|
248
|
+
*/
|
|
249
|
+
class CoreMemoryClient {
|
|
11
250
|
constructor(config) {
|
|
12
251
|
this.config = {
|
|
13
252
|
timeout: 30000,
|
|
14
|
-
useGateway: true,
|
|
15
253
|
...config
|
|
16
254
|
};
|
|
17
255
|
this.baseHeaders = {
|
|
18
256
|
'Content-Type': 'application/json',
|
|
19
|
-
'User-Agent': '@lanonasis/memory-client/
|
|
257
|
+
'User-Agent': '@lanonasis/memory-client/2.0.0',
|
|
258
|
+
'X-Project-Scope': 'lanonasis-maas', // Required by backend auth middleware
|
|
20
259
|
...config.headers
|
|
21
260
|
};
|
|
22
261
|
// Set authentication headers
|
|
@@ -26,48 +265,171 @@ class MemoryClient {
|
|
|
26
265
|
else if (config.apiKey) {
|
|
27
266
|
this.baseHeaders['X-API-Key'] = config.apiKey;
|
|
28
267
|
}
|
|
268
|
+
// Add organization ID header if provided
|
|
269
|
+
if (config.organizationId) {
|
|
270
|
+
this.baseHeaders['X-Organization-ID'] = config.organizationId;
|
|
271
|
+
}
|
|
29
272
|
}
|
|
30
273
|
/**
|
|
31
|
-
*
|
|
274
|
+
* Enrich request body with organization context if configured
|
|
275
|
+
* This ensures the API has the organization_id even if not in auth token
|
|
276
|
+
*/
|
|
277
|
+
enrichWithOrgContext(body) {
|
|
278
|
+
// If organizationId is configured, include it in the request body
|
|
279
|
+
if (this.config.organizationId && !body.organization_id) {
|
|
280
|
+
return {
|
|
281
|
+
...body,
|
|
282
|
+
organization_id: this.config.organizationId
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
// Fallback to userId if no organizationId configured
|
|
286
|
+
if (!this.config.organizationId && this.config.userId && !body.organization_id) {
|
|
287
|
+
return {
|
|
288
|
+
...body,
|
|
289
|
+
organization_id: this.config.userId
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return body;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Make an HTTP request to the API with retry support
|
|
32
296
|
*/
|
|
33
297
|
async request(endpoint, options = {}) {
|
|
298
|
+
const startTime = Date.now();
|
|
299
|
+
const maxRetries = this.config.retry?.maxRetries ?? 3;
|
|
300
|
+
const baseDelay = this.config.retry?.retryDelay ?? 1000;
|
|
301
|
+
const backoff = this.config.retry?.backoff ?? 'exponential';
|
|
302
|
+
// Call onRequest hook if provided
|
|
303
|
+
if (this.config.onRequest) {
|
|
304
|
+
try {
|
|
305
|
+
this.config.onRequest(endpoint);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.warn('onRequest hook error:', error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
34
311
|
// Handle gateway vs direct API URL formatting
|
|
35
312
|
const baseUrl = this.config.apiUrl.includes('/api')
|
|
36
313
|
? this.config.apiUrl.replace('/api', '')
|
|
37
314
|
: this.config.apiUrl;
|
|
38
315
|
const url = `${baseUrl}/api/v1${endpoint}`;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
data
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
316
|
+
let lastError;
|
|
317
|
+
let attempt = 0;
|
|
318
|
+
while (attempt <= maxRetries) {
|
|
319
|
+
try {
|
|
320
|
+
const controller = new AbortController();
|
|
321
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
322
|
+
const response = await fetch(url, {
|
|
323
|
+
headers: { ...this.baseHeaders, ...options.headers },
|
|
324
|
+
signal: controller.signal,
|
|
325
|
+
...options,
|
|
326
|
+
});
|
|
327
|
+
clearTimeout(timeoutId);
|
|
328
|
+
let data;
|
|
329
|
+
const contentType = response.headers.get('content-type');
|
|
330
|
+
if (contentType && contentType.includes('application/json')) {
|
|
331
|
+
data = await response.json();
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
data = await response.text();
|
|
335
|
+
}
|
|
336
|
+
if (!response.ok) {
|
|
337
|
+
const error = createErrorFromResponse(response.status, response.statusText, data);
|
|
338
|
+
// Only retry on retryable errors (5xx, 429, 408)
|
|
339
|
+
if (isRetryableError(response.status) && attempt < maxRetries) {
|
|
340
|
+
lastError = error;
|
|
341
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
342
|
+
await sleep(delay);
|
|
343
|
+
attempt++;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
// Call onError hook if provided
|
|
347
|
+
if (this.config.onError) {
|
|
348
|
+
try {
|
|
349
|
+
this.config.onError(error);
|
|
350
|
+
}
|
|
351
|
+
catch (hookError) {
|
|
352
|
+
console.warn('onError hook error:', hookError);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return { error, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
356
|
+
}
|
|
357
|
+
// Call onResponse hook if provided
|
|
358
|
+
if (this.config.onResponse) {
|
|
359
|
+
try {
|
|
360
|
+
const duration = Date.now() - startTime;
|
|
361
|
+
this.config.onResponse(endpoint, duration);
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
console.warn('onResponse hook error:', error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return { data, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
55
368
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
369
|
+
catch (error) {
|
|
370
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
371
|
+
const timeoutError = createErrorResponse('Request timeout', 'TIMEOUT_ERROR', 408);
|
|
372
|
+
// Retry on timeout
|
|
373
|
+
if (attempt < maxRetries) {
|
|
374
|
+
lastError = timeoutError;
|
|
375
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
376
|
+
await sleep(delay);
|
|
377
|
+
attempt++;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (this.config.onError) {
|
|
381
|
+
try {
|
|
382
|
+
this.config.onError(timeoutError);
|
|
383
|
+
}
|
|
384
|
+
catch (hookError) {
|
|
385
|
+
console.warn('onError hook error:', hookError);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return { error: timeoutError, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
389
|
+
}
|
|
390
|
+
const networkError = createErrorResponse(error instanceof Error ? error.message : 'Network error', 'NETWORK_ERROR');
|
|
391
|
+
// Retry on network errors
|
|
392
|
+
if (attempt < maxRetries) {
|
|
393
|
+
lastError = networkError;
|
|
394
|
+
const delay = calculateRetryDelay(attempt, baseDelay, backoff);
|
|
395
|
+
await sleep(delay);
|
|
396
|
+
attempt++;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (this.config.onError) {
|
|
400
|
+
try {
|
|
401
|
+
this.config.onError(networkError);
|
|
402
|
+
}
|
|
403
|
+
catch (hookError) {
|
|
404
|
+
console.warn('onError hook error:', hookError);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return { error: networkError, meta: { duration: Date.now() - startTime, retries: attempt } };
|
|
60
408
|
}
|
|
61
|
-
return { data };
|
|
62
409
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
410
|
+
// Should never reach here, but handle it gracefully
|
|
411
|
+
return {
|
|
412
|
+
error: lastError ?? createErrorResponse('Max retries exceeded', 'API_ERROR'),
|
|
413
|
+
meta: { duration: Date.now() - startTime, retries: attempt }
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Validate input using Zod schema and return validation error if invalid
|
|
418
|
+
*/
|
|
419
|
+
validateInput(schema, data) {
|
|
420
|
+
const result = schema.safeParse(data);
|
|
421
|
+
if (!result.success) {
|
|
422
|
+
// Extract error details from Zod error
|
|
423
|
+
const zodError = result.error;
|
|
424
|
+
const details = zodError?.issues?.map(issue => ({
|
|
425
|
+
field: issue.path.map(String).join('.'),
|
|
426
|
+
message: issue.message
|
|
427
|
+
})) ?? [];
|
|
67
428
|
return {
|
|
68
|
-
error:
|
|
429
|
+
error: createErrorResponse('Validation failed', 'VALIDATION_ERROR', 400, details)
|
|
69
430
|
};
|
|
70
431
|
}
|
|
432
|
+
return null;
|
|
71
433
|
}
|
|
72
434
|
/**
|
|
73
435
|
* Test the API connection and authentication
|
|
@@ -77,12 +439,18 @@ class MemoryClient {
|
|
|
77
439
|
}
|
|
78
440
|
// Memory Operations
|
|
79
441
|
/**
|
|
80
|
-
* Create a new memory
|
|
442
|
+
* Create a new memory with validation
|
|
81
443
|
*/
|
|
82
444
|
async createMemory(memory) {
|
|
445
|
+
// Validate input before making request
|
|
446
|
+
const validationError = this.validateInput(createMemorySchema, memory);
|
|
447
|
+
if (validationError) {
|
|
448
|
+
return { error: validationError.error };
|
|
449
|
+
}
|
|
450
|
+
const enrichedMemory = this.enrichWithOrgContext(memory);
|
|
83
451
|
return this.request('/memory', {
|
|
84
452
|
method: 'POST',
|
|
85
|
-
body: JSON.stringify(
|
|
453
|
+
body: JSON.stringify(enrichedMemory)
|
|
86
454
|
});
|
|
87
455
|
}
|
|
88
456
|
/**
|
|
@@ -92,9 +460,14 @@ class MemoryClient {
|
|
|
92
460
|
return this.request(`/memory/${encodeURIComponent(id)}`);
|
|
93
461
|
}
|
|
94
462
|
/**
|
|
95
|
-
* Update an existing memory
|
|
463
|
+
* Update an existing memory with validation
|
|
96
464
|
*/
|
|
97
465
|
async updateMemory(id, updates) {
|
|
466
|
+
// Validate input before making request
|
|
467
|
+
const validationError = this.validateInput(updateMemorySchema, updates);
|
|
468
|
+
if (validationError) {
|
|
469
|
+
return { error: validationError.error };
|
|
470
|
+
}
|
|
98
471
|
return this.request(`/memory/${encodeURIComponent(id)}`, {
|
|
99
472
|
method: 'PUT',
|
|
100
473
|
body: JSON.stringify(updates)
|
|
@@ -128,31 +501,45 @@ class MemoryClient {
|
|
|
128
501
|
return this.request(endpoint);
|
|
129
502
|
}
|
|
130
503
|
/**
|
|
131
|
-
* Search memories using semantic search
|
|
504
|
+
* Search memories using semantic search with validation
|
|
132
505
|
*/
|
|
133
506
|
async searchMemories(request) {
|
|
507
|
+
// Validate input before making request
|
|
508
|
+
const validationError = this.validateInput(searchMemorySchema, request);
|
|
509
|
+
if (validationError) {
|
|
510
|
+
// Return error response (data will be undefined, only error is set)
|
|
511
|
+
return { error: validationError.error };
|
|
512
|
+
}
|
|
513
|
+
const enrichedRequest = this.enrichWithOrgContext(request);
|
|
134
514
|
return this.request('/memory/search', {
|
|
135
515
|
method: 'POST',
|
|
136
|
-
body: JSON.stringify(
|
|
516
|
+
body: JSON.stringify(enrichedRequest)
|
|
137
517
|
});
|
|
138
518
|
}
|
|
139
519
|
/**
|
|
140
520
|
* Bulk delete multiple memories
|
|
141
521
|
*/
|
|
142
522
|
async bulkDeleteMemories(memoryIds) {
|
|
523
|
+
const enrichedRequest = this.enrichWithOrgContext({ memory_ids: memoryIds });
|
|
143
524
|
return this.request('/memory/bulk/delete', {
|
|
144
525
|
method: 'POST',
|
|
145
|
-
body: JSON.stringify(
|
|
526
|
+
body: JSON.stringify(enrichedRequest)
|
|
146
527
|
});
|
|
147
528
|
}
|
|
148
529
|
// Topic Operations
|
|
149
530
|
/**
|
|
150
|
-
* Create a new topic
|
|
531
|
+
* Create a new topic with validation
|
|
151
532
|
*/
|
|
152
533
|
async createTopic(topic) {
|
|
534
|
+
// Validate input before making request
|
|
535
|
+
const validationError = this.validateInput(createTopicSchema, topic);
|
|
536
|
+
if (validationError) {
|
|
537
|
+
return { error: validationError.error };
|
|
538
|
+
}
|
|
539
|
+
const enrichedTopic = this.enrichWithOrgContext(topic);
|
|
153
540
|
return this.request('/topics', {
|
|
154
541
|
method: 'POST',
|
|
155
|
-
body: JSON.stringify(
|
|
542
|
+
body: JSON.stringify(enrichedTopic)
|
|
156
543
|
});
|
|
157
544
|
}
|
|
158
545
|
/**
|
|
@@ -190,6 +577,182 @@ class MemoryClient {
|
|
|
190
577
|
async getMemoryStats() {
|
|
191
578
|
return this.request('/memory/stats');
|
|
192
579
|
}
|
|
580
|
+
// ========================================
|
|
581
|
+
// Intelligence Features (v2.0)
|
|
582
|
+
// ========================================
|
|
583
|
+
/**
|
|
584
|
+
* Create a memory with preprocessing options (chunking, intelligence extraction)
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```typescript
|
|
588
|
+
* const result = await client.createMemoryWithPreprocessing({
|
|
589
|
+
* title: 'Auth System Docs',
|
|
590
|
+
* content: 'Long content...',
|
|
591
|
+
* memory_type: 'knowledge',
|
|
592
|
+
* preprocessing: {
|
|
593
|
+
* chunking: { strategy: 'semantic', maxChunkSize: 1000 },
|
|
594
|
+
* extractMetadata: true
|
|
595
|
+
* }
|
|
596
|
+
* });
|
|
597
|
+
* ```
|
|
598
|
+
*/
|
|
599
|
+
async createMemoryWithPreprocessing(memory) {
|
|
600
|
+
// Validate base memory fields
|
|
601
|
+
const validationError = this.validateInput(createMemorySchema, memory);
|
|
602
|
+
if (validationError) {
|
|
603
|
+
return { error: validationError.error };
|
|
604
|
+
}
|
|
605
|
+
const enrichedMemory = this.enrichWithOrgContext(memory);
|
|
606
|
+
return this.request('/memory', {
|
|
607
|
+
method: 'POST',
|
|
608
|
+
body: JSON.stringify(enrichedMemory)
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Update a memory with re-chunking and embedding regeneration
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```typescript
|
|
616
|
+
* const result = await client.updateMemoryWithPreprocessing('mem_123', {
|
|
617
|
+
* content: 'Updated content...',
|
|
618
|
+
* rechunk: true,
|
|
619
|
+
* regenerate_embedding: true
|
|
620
|
+
* });
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
async updateMemoryWithPreprocessing(id, updates) {
|
|
624
|
+
const validationError = this.validateInput(updateMemorySchema, updates);
|
|
625
|
+
if (validationError) {
|
|
626
|
+
return { error: validationError.error };
|
|
627
|
+
}
|
|
628
|
+
return this.request(`/memory/${encodeURIComponent(id)}`, {
|
|
629
|
+
method: 'PUT',
|
|
630
|
+
body: JSON.stringify(updates)
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Enhanced semantic search with hybrid mode (vector + text)
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* ```typescript
|
|
638
|
+
* const result = await client.enhancedSearch({
|
|
639
|
+
* query: 'authentication flow',
|
|
640
|
+
* search_mode: 'hybrid',
|
|
641
|
+
* filters: { tags: ['auth'], project_id: 'proj_123' },
|
|
642
|
+
* include_chunks: true
|
|
643
|
+
* });
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
async enhancedSearch(request) {
|
|
647
|
+
const validationError = this.validateInput(enhancedSearchSchema, request);
|
|
648
|
+
if (validationError) {
|
|
649
|
+
return { error: validationError.error };
|
|
650
|
+
}
|
|
651
|
+
const enrichedRequest = this.enrichWithOrgContext(request);
|
|
652
|
+
return this.request('/memory/search', {
|
|
653
|
+
method: 'POST',
|
|
654
|
+
body: JSON.stringify(enrichedRequest)
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
// ========================================
|
|
658
|
+
// Analytics Operations
|
|
659
|
+
// ========================================
|
|
660
|
+
/**
|
|
661
|
+
* Get search analytics data
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* ```typescript
|
|
665
|
+
* const analytics = await client.getSearchAnalytics({
|
|
666
|
+
* from: '2025-01-01',
|
|
667
|
+
* to: '2025-12-31',
|
|
668
|
+
* group_by: 'day'
|
|
669
|
+
* });
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
async getSearchAnalytics(options = {}) {
|
|
673
|
+
const validationError = this.validateInput(analyticsDateRangeSchema, options);
|
|
674
|
+
if (validationError) {
|
|
675
|
+
return { error: validationError.error };
|
|
676
|
+
}
|
|
677
|
+
const params = new URLSearchParams();
|
|
678
|
+
if (options.from)
|
|
679
|
+
params.append('from', options.from);
|
|
680
|
+
if (options.to)
|
|
681
|
+
params.append('to', options.to);
|
|
682
|
+
if (options.group_by)
|
|
683
|
+
params.append('group_by', options.group_by);
|
|
684
|
+
const queryString = params.toString();
|
|
685
|
+
const endpoint = queryString ? `/analytics/search?${queryString}` : '/analytics/search';
|
|
686
|
+
return this.request(endpoint);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Get memory access patterns
|
|
690
|
+
*
|
|
691
|
+
* @example
|
|
692
|
+
* ```typescript
|
|
693
|
+
* const patterns = await client.getAccessPatterns({
|
|
694
|
+
* from: '2025-01-01',
|
|
695
|
+
* to: '2025-12-31'
|
|
696
|
+
* });
|
|
697
|
+
* console.log(patterns.data?.most_accessed);
|
|
698
|
+
* ```
|
|
699
|
+
*/
|
|
700
|
+
async getAccessPatterns(options = {}) {
|
|
701
|
+
const params = new URLSearchParams();
|
|
702
|
+
if (options.from)
|
|
703
|
+
params.append('from', options.from);
|
|
704
|
+
if (options.to)
|
|
705
|
+
params.append('to', options.to);
|
|
706
|
+
const queryString = params.toString();
|
|
707
|
+
const endpoint = queryString ? `/analytics/access?${queryString}` : '/analytics/access';
|
|
708
|
+
return this.request(endpoint);
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Get extended memory statistics with storage and activity metrics
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```typescript
|
|
715
|
+
* const stats = await client.getExtendedStats();
|
|
716
|
+
* console.log(`Total chunks: ${stats.data?.storage.total_chunks}`);
|
|
717
|
+
* console.log(`Created today: ${stats.data?.activity.created_today}`);
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
async getExtendedStats() {
|
|
721
|
+
return this.request('/analytics/stats');
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Get topic with its memories
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```typescript
|
|
728
|
+
* const topic = await client.getTopicWithMemories('topic_123');
|
|
729
|
+
* console.log(topic.data?.memories);
|
|
730
|
+
* ```
|
|
731
|
+
*/
|
|
732
|
+
async getTopicWithMemories(topicId, options = {}) {
|
|
733
|
+
const params = new URLSearchParams();
|
|
734
|
+
if (options.limit)
|
|
735
|
+
params.append('limit', String(options.limit));
|
|
736
|
+
if (options.offset)
|
|
737
|
+
params.append('offset', String(options.offset));
|
|
738
|
+
const queryString = params.toString();
|
|
739
|
+
const endpoint = queryString
|
|
740
|
+
? `/topics/${encodeURIComponent(topicId)}/memories?${queryString}`
|
|
741
|
+
: `/topics/${encodeURIComponent(topicId)}/memories`;
|
|
742
|
+
return this.request(endpoint);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Get topics in hierarchical structure
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* ```typescript
|
|
749
|
+
* const topics = await client.getTopicsHierarchy();
|
|
750
|
+
* // Returns nested topic tree with children
|
|
751
|
+
* ```
|
|
752
|
+
*/
|
|
753
|
+
async getTopicsHierarchy() {
|
|
754
|
+
return this.request('/topics?include_hierarchy=true');
|
|
755
|
+
}
|
|
193
756
|
// Utility Methods
|
|
194
757
|
/**
|
|
195
758
|
* Update authentication token
|
|
@@ -231,17 +794,431 @@ class MemoryClient {
|
|
|
231
794
|
}
|
|
232
795
|
}
|
|
233
796
|
/**
|
|
234
|
-
* Factory function to create a new Memory Client instance
|
|
797
|
+
* Factory function to create a new Core Memory Client instance
|
|
235
798
|
*/
|
|
236
799
|
function createMemoryClient(config) {
|
|
237
|
-
return new
|
|
800
|
+
return new CoreMemoryClient(config);
|
|
238
801
|
}
|
|
239
802
|
|
|
803
|
+
/**
|
|
804
|
+
* Error handling for Memory Client
|
|
805
|
+
* Browser-safe, no Node.js dependencies
|
|
806
|
+
*/
|
|
807
|
+
/**
|
|
808
|
+
* Standardized error codes for programmatic error handling
|
|
809
|
+
*/
|
|
810
|
+
const ERROR_CODES = [
|
|
811
|
+
'API_ERROR',
|
|
812
|
+
'AUTH_ERROR',
|
|
813
|
+
'VALIDATION_ERROR',
|
|
814
|
+
'TIMEOUT_ERROR',
|
|
815
|
+
'RATE_LIMIT_ERROR',
|
|
816
|
+
'NOT_FOUND',
|
|
817
|
+
'NETWORK_ERROR',
|
|
818
|
+
'FORBIDDEN',
|
|
819
|
+
'CONFLICT',
|
|
820
|
+
'SERVER_ERROR'
|
|
821
|
+
];
|
|
822
|
+
/**
|
|
823
|
+
* Type guard to check if an object is an ApiErrorResponse
|
|
824
|
+
*/
|
|
825
|
+
function isApiErrorResponse(value) {
|
|
826
|
+
return (typeof value === 'object' &&
|
|
827
|
+
value !== null &&
|
|
828
|
+
'code' in value &&
|
|
829
|
+
'message' in value &&
|
|
830
|
+
typeof value.code === 'string' &&
|
|
831
|
+
typeof value.message === 'string');
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Base error class for Memory Client errors
|
|
835
|
+
*/
|
|
836
|
+
class MemoryClientError extends Error {
|
|
837
|
+
constructor(message, code = 'API_ERROR', statusCode, details) {
|
|
838
|
+
super(message);
|
|
839
|
+
this.code = code;
|
|
840
|
+
this.statusCode = statusCode;
|
|
841
|
+
this.details = details;
|
|
842
|
+
this.name = 'MemoryClientError';
|
|
843
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
844
|
+
if (Error.captureStackTrace) {
|
|
845
|
+
Error.captureStackTrace(this, MemoryClientError);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Convert to ApiErrorResponse for consistent API responses
|
|
850
|
+
*/
|
|
851
|
+
toResponse() {
|
|
852
|
+
return {
|
|
853
|
+
code: this.code,
|
|
854
|
+
message: this.message,
|
|
855
|
+
statusCode: this.statusCode,
|
|
856
|
+
details: this.details,
|
|
857
|
+
timestamp: new Date().toISOString()
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Network/API error
|
|
863
|
+
*/
|
|
864
|
+
class ApiError extends MemoryClientError {
|
|
865
|
+
constructor(message, statusCode, details) {
|
|
866
|
+
super(message, 'API_ERROR', statusCode, details);
|
|
867
|
+
this.name = 'ApiError';
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Create from an HTTP response
|
|
871
|
+
*/
|
|
872
|
+
static fromResponse(status, statusText, body) {
|
|
873
|
+
let message = `HTTP ${status}: ${statusText}`;
|
|
874
|
+
let details = undefined;
|
|
875
|
+
if (body && typeof body === 'object') {
|
|
876
|
+
const bodyObj = body;
|
|
877
|
+
if (typeof bodyObj.error === 'string') {
|
|
878
|
+
message = bodyObj.error;
|
|
879
|
+
}
|
|
880
|
+
else if (typeof bodyObj.message === 'string') {
|
|
881
|
+
message = bodyObj.message;
|
|
882
|
+
}
|
|
883
|
+
if (bodyObj.details) {
|
|
884
|
+
details = bodyObj.details;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return new ApiError(message, status, details);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Authentication error
|
|
892
|
+
*/
|
|
893
|
+
class AuthenticationError extends MemoryClientError {
|
|
894
|
+
constructor(message = 'Authentication required') {
|
|
895
|
+
super(message, 'AUTH_ERROR', 401);
|
|
896
|
+
this.name = 'AuthenticationError';
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Validation error with field-level details
|
|
901
|
+
*/
|
|
902
|
+
class ValidationError extends MemoryClientError {
|
|
903
|
+
constructor(message, details) {
|
|
904
|
+
super(message, 'VALIDATION_ERROR', 400, details);
|
|
905
|
+
this.name = 'ValidationError';
|
|
906
|
+
// Parse validation details into field errors
|
|
907
|
+
this.validationErrors = [];
|
|
908
|
+
if (Array.isArray(details)) {
|
|
909
|
+
this.validationErrors = details.filter((item) => typeof item === 'object' &&
|
|
910
|
+
item !== null &&
|
|
911
|
+
typeof item.field === 'string' &&
|
|
912
|
+
typeof item.message === 'string');
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Create from Zod error
|
|
917
|
+
*/
|
|
918
|
+
static fromZodError(error) {
|
|
919
|
+
const details = error.issues.map(issue => ({
|
|
920
|
+
field: issue.path.join('.'),
|
|
921
|
+
message: issue.message
|
|
922
|
+
}));
|
|
923
|
+
return new ValidationError('Validation failed', details);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Timeout error
|
|
928
|
+
*/
|
|
929
|
+
class TimeoutError extends MemoryClientError {
|
|
930
|
+
constructor(message = 'Request timeout') {
|
|
931
|
+
super(message, 'TIMEOUT_ERROR', 408);
|
|
932
|
+
this.name = 'TimeoutError';
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Rate limit error with retry-after info
|
|
937
|
+
*/
|
|
938
|
+
class RateLimitError extends MemoryClientError {
|
|
939
|
+
constructor(message = 'Rate limit exceeded', retryAfter) {
|
|
940
|
+
super(message, 'RATE_LIMIT_ERROR', 429, { retryAfter });
|
|
941
|
+
this.name = 'RateLimitError';
|
|
942
|
+
this.retryAfter = retryAfter;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Not found error
|
|
947
|
+
*/
|
|
948
|
+
class NotFoundError extends MemoryClientError {
|
|
949
|
+
constructor(resource) {
|
|
950
|
+
super(`${resource} not found`, 'NOT_FOUND', 404);
|
|
951
|
+
this.name = 'NotFoundError';
|
|
952
|
+
this.resource = resource;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Network error (no response received)
|
|
957
|
+
*/
|
|
958
|
+
class NetworkError extends MemoryClientError {
|
|
959
|
+
constructor(message = 'Network error') {
|
|
960
|
+
super(message, 'NETWORK_ERROR');
|
|
961
|
+
this.name = 'NetworkError';
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Server error (5xx responses)
|
|
966
|
+
*/
|
|
967
|
+
class ServerError extends MemoryClientError {
|
|
968
|
+
constructor(message, statusCode = 500) {
|
|
969
|
+
super(message, 'SERVER_ERROR', statusCode);
|
|
970
|
+
this.name = 'ServerError';
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Create appropriate error class from status code
|
|
975
|
+
*/
|
|
976
|
+
function createErrorFromStatus(status, message, details) {
|
|
977
|
+
switch (status) {
|
|
978
|
+
case 400:
|
|
979
|
+
return new ValidationError(message, details);
|
|
980
|
+
case 401:
|
|
981
|
+
return new AuthenticationError(message);
|
|
982
|
+
case 404:
|
|
983
|
+
return new NotFoundError(message);
|
|
984
|
+
case 408:
|
|
985
|
+
return new TimeoutError(message);
|
|
986
|
+
case 429:
|
|
987
|
+
return new RateLimitError(message);
|
|
988
|
+
case 500:
|
|
989
|
+
case 502:
|
|
990
|
+
case 503:
|
|
991
|
+
case 504:
|
|
992
|
+
return new ServerError(message, status);
|
|
993
|
+
default:
|
|
994
|
+
return new ApiError(message, status, details);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* @lanonasis/memory-client
|
|
1000
|
+
*
|
|
1001
|
+
* Universal Memory as a Service (MaaS) Client SDK for Lanonasis
|
|
1002
|
+
* Intelligent memory management with semantic search capabilities
|
|
1003
|
+
*
|
|
1004
|
+
* v2.0.0 - Universal SDK Redesign
|
|
1005
|
+
* "Drop In and Sleep" Architecture - Works everywhere with zero configuration
|
|
1006
|
+
*
|
|
1007
|
+
* @example Browser/Web App
|
|
1008
|
+
* ```ts
|
|
1009
|
+
* import { createMemoryClient } from '@lanonasis/memory-client/core';
|
|
1010
|
+
* const client = createMemoryClient({ apiKey: 'your-key' });
|
|
1011
|
+
* ```
|
|
1012
|
+
*
|
|
1013
|
+
* @example Node.js
|
|
1014
|
+
* ```ts
|
|
1015
|
+
* import { createNodeMemoryClient } from '@lanonasis/memory-client/node';
|
|
1016
|
+
* const client = await createNodeMemoryClient({ apiKey: process.env.KEY });
|
|
1017
|
+
* ```
|
|
1018
|
+
*
|
|
1019
|
+
* @example React
|
|
1020
|
+
* ```tsx
|
|
1021
|
+
* import { MemoryProvider, useMemories } from '@lanonasis/memory-client/react';
|
|
1022
|
+
* ```
|
|
1023
|
+
*
|
|
1024
|
+
* @example Vue
|
|
1025
|
+
* ```ts
|
|
1026
|
+
* import { createMemoryPlugin, useMemories } from '@lanonasis/memory-client/vue';
|
|
1027
|
+
* ```
|
|
1028
|
+
*/
|
|
1029
|
+
// ========================================
|
|
1030
|
+
// Internal Imports (for use in this file)
|
|
1031
|
+
// ========================================
|
|
1032
|
+
// ========================================
|
|
1033
|
+
// Constants
|
|
1034
|
+
// ========================================
|
|
1035
|
+
const VERSION = '2.0.0';
|
|
1036
|
+
const CLIENT_NAME = '@lanonasis/memory-client';
|
|
1037
|
+
// ========================================
|
|
1038
|
+
// Environment Detection
|
|
1039
|
+
// ========================================
|
|
1040
|
+
const isBrowser = typeof window !== 'undefined';
|
|
1041
|
+
const isNode = typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node;
|
|
1042
|
+
const isEdge = !isBrowser && !isNode;
|
|
1043
|
+
/**
|
|
1044
|
+
* Get the current runtime environment
|
|
1045
|
+
*/
|
|
1046
|
+
function getEnvironment() {
|
|
1047
|
+
if (isBrowser)
|
|
1048
|
+
return 'browser';
|
|
1049
|
+
if (isNode)
|
|
1050
|
+
return 'node';
|
|
1051
|
+
return 'edge';
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Auto-detecting client factory - "Drop In and Sleep" architecture
|
|
1055
|
+
*
|
|
1056
|
+
* Automatically detects the runtime environment and returns the appropriate client:
|
|
1057
|
+
* - Browser/Edge: Returns CoreMemoryClient (lightweight, browser-safe)
|
|
1058
|
+
* - Node.js: Returns EnhancedMemoryClient (with CLI/MCP support)
|
|
1059
|
+
*
|
|
1060
|
+
* @example
|
|
1061
|
+
* ```typescript
|
|
1062
|
+
* import { createClient } from '@lanonasis/memory-client';
|
|
1063
|
+
*
|
|
1064
|
+
* // Works in any environment!
|
|
1065
|
+
* const client = await createClient({
|
|
1066
|
+
* apiUrl: 'https://api.lanonasis.com',
|
|
1067
|
+
* apiKey: 'your-key'
|
|
1068
|
+
* });
|
|
1069
|
+
*
|
|
1070
|
+
* const memories = await client.listMemories();
|
|
1071
|
+
* ```
|
|
1072
|
+
*/
|
|
1073
|
+
async function createClient(config) {
|
|
1074
|
+
const environment = getEnvironment();
|
|
1075
|
+
if (environment === 'node') {
|
|
1076
|
+
try {
|
|
1077
|
+
// Dynamic import for Node.js client to avoid bundling in browser
|
|
1078
|
+
const { createNodeMemoryClient } = await Promise.resolve().then(function () { return index; });
|
|
1079
|
+
return await createNodeMemoryClient({
|
|
1080
|
+
...config,
|
|
1081
|
+
preferCLI: config.preferCLI ?? true,
|
|
1082
|
+
enableMCP: config.enableMCP ?? true
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
catch {
|
|
1086
|
+
// Fallback to core client if Node module fails to load
|
|
1087
|
+
console.warn('Failed to load Node.js client, falling back to core client');
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
// Browser, Edge, or fallback
|
|
1091
|
+
const clientConfig = {
|
|
1092
|
+
apiUrl: config.apiUrl,
|
|
1093
|
+
apiKey: config.apiKey,
|
|
1094
|
+
authToken: config.authToken,
|
|
1095
|
+
organizationId: config.organizationId,
|
|
1096
|
+
timeout: config.timeout ?? (environment === 'edge' ? 5000 : 30000),
|
|
1097
|
+
headers: config.headers,
|
|
1098
|
+
retry: config.retry
|
|
1099
|
+
};
|
|
1100
|
+
return createMemoryClient(clientConfig);
|
|
1101
|
+
}
|
|
1102
|
+
// ========================================
|
|
1103
|
+
// Default Configurations
|
|
1104
|
+
// ========================================
|
|
1105
|
+
const defaultConfigs = {
|
|
1106
|
+
development: {
|
|
1107
|
+
apiUrl: 'http://localhost:3001',
|
|
1108
|
+
timeout: 30000,
|
|
1109
|
+
},
|
|
1110
|
+
production: {
|
|
1111
|
+
apiUrl: 'https://api.lanonasis.com',
|
|
1112
|
+
timeout: 15000,
|
|
1113
|
+
},
|
|
1114
|
+
edge: {
|
|
1115
|
+
apiUrl: 'https://api.lanonasis.com',
|
|
1116
|
+
timeout: 5000,
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
// Note: Enhanced client requires Node.js, so we don't export it from main entry
|
|
1120
|
+
// Users should import from '@lanonasis/memory-client/node' instead
|
|
1121
|
+
// ========================================
|
|
1122
|
+
// Usage Instructions
|
|
1123
|
+
// ========================================
|
|
1124
|
+
/**
|
|
1125
|
+
* # @lanonasis/memory-client v2.0
|
|
1126
|
+
*
|
|
1127
|
+
* ## Quick Start
|
|
1128
|
+
*
|
|
1129
|
+
* ### Browser / Web App
|
|
1130
|
+
* ```bash
|
|
1131
|
+
* npm install @lanonasis/memory-client
|
|
1132
|
+
* ```
|
|
1133
|
+
* ```typescript
|
|
1134
|
+
* import { createMemoryClient } from '@lanonasis/memory-client/core';
|
|
1135
|
+
*
|
|
1136
|
+
* const client = createMemoryClient({
|
|
1137
|
+
* apiUrl: 'https://api.lanonasis.com',
|
|
1138
|
+
* apiKey: 'your-key-here'
|
|
1139
|
+
* });
|
|
1140
|
+
*
|
|
1141
|
+
* const memories = await client.listMemories();
|
|
1142
|
+
* ```
|
|
1143
|
+
*
|
|
1144
|
+
* ### Node.js with CLI Support
|
|
1145
|
+
* ```typescript
|
|
1146
|
+
* import { createNodeMemoryClient } from '@lanonasis/memory-client/node';
|
|
1147
|
+
*
|
|
1148
|
+
* const client = await createNodeMemoryClient({
|
|
1149
|
+
* apiKey: process.env.LANONASIS_KEY,
|
|
1150
|
+
* preferCLI: true // Automatically uses CLI if available
|
|
1151
|
+
* });
|
|
1152
|
+
*
|
|
1153
|
+
* const result = await client.listMemories();
|
|
1154
|
+
* console.log(`Using: ${result.source}`); // 'cli' or 'api'
|
|
1155
|
+
* ```
|
|
1156
|
+
*
|
|
1157
|
+
* ### React
|
|
1158
|
+
* ```tsx
|
|
1159
|
+
* import { MemoryProvider, useMemories } from '@lanonasis/memory-client/react';
|
|
1160
|
+
*
|
|
1161
|
+
* function App() {
|
|
1162
|
+
* return (
|
|
1163
|
+
* <MemoryProvider apiKey="your-key">
|
|
1164
|
+
* <MemoryList />
|
|
1165
|
+
* </MemoryProvider>
|
|
1166
|
+
* );
|
|
1167
|
+
* }
|
|
1168
|
+
*
|
|
1169
|
+
* function MemoryList() {
|
|
1170
|
+
* const { memories, loading } = useMemories();
|
|
1171
|
+
* if (loading) return <div>Loading...</div>;
|
|
1172
|
+
* return <div>{memories.map(m => <div key={m.id}>{m.title}</div>)}</div>;
|
|
1173
|
+
* }
|
|
1174
|
+
* ```
|
|
1175
|
+
*
|
|
1176
|
+
* ### Vue 3
|
|
1177
|
+
* ```typescript
|
|
1178
|
+
* import { createMemoryPlugin, useMemories } from '@lanonasis/memory-client/vue';
|
|
1179
|
+
*
|
|
1180
|
+
* const app = createApp(App);
|
|
1181
|
+
* app.use(createMemoryPlugin({ apiKey: 'your-key' }));
|
|
1182
|
+
* ```
|
|
1183
|
+
*
|
|
1184
|
+
* ### Edge Functions (Cloudflare Workers, Vercel Edge)
|
|
1185
|
+
* ```typescript
|
|
1186
|
+
* import { createMemoryClient } from '@lanonasis/memory-client/core';
|
|
1187
|
+
* import { edgePreset } from '@lanonasis/memory-client/presets';
|
|
1188
|
+
*
|
|
1189
|
+
* export default {
|
|
1190
|
+
* async fetch(request: Request, env: Env) {
|
|
1191
|
+
* const client = createMemoryClient(edgePreset({
|
|
1192
|
+
* apiKey: env.LANONASIS_KEY
|
|
1193
|
+
* }));
|
|
1194
|
+
* const memories = await client.searchMemories({ query: 'test' });
|
|
1195
|
+
* return Response.json(memories.data);
|
|
1196
|
+
* }
|
|
1197
|
+
* };
|
|
1198
|
+
* ```
|
|
1199
|
+
*
|
|
1200
|
+
* ## Bundle Sizes
|
|
1201
|
+
*
|
|
1202
|
+
* - **Core** (browser): ~15KB gzipped
|
|
1203
|
+
* - **Node** (with CLI): ~35KB gzipped
|
|
1204
|
+
* - **React**: ~18KB gzipped (+ React)
|
|
1205
|
+
* - **Vue**: ~17KB gzipped (+ Vue)
|
|
1206
|
+
* - **Presets**: ~2KB gzipped
|
|
1207
|
+
*
|
|
1208
|
+
* ## Documentation
|
|
1209
|
+
*
|
|
1210
|
+
* - Full docs: https://docs.lanonasis.com/sdk
|
|
1211
|
+
* - API reference: https://docs.lanonasis.com/api
|
|
1212
|
+
* - Examples: https://github.com/lanonasis/examples
|
|
1213
|
+
*/
|
|
1214
|
+
|
|
240
1215
|
/**
|
|
241
1216
|
* CLI Integration Module for Memory Client SDK
|
|
242
1217
|
*
|
|
243
1218
|
* Provides intelligent CLI detection and MCP channel utilization
|
|
244
1219
|
* when @lanonasis/cli v1.5.2+ is available in the environment
|
|
1220
|
+
*
|
|
1221
|
+
* IMPORTANT: This file imports Node.js modules and should only be used in Node.js environments
|
|
245
1222
|
*/
|
|
246
1223
|
const execAsync = util.promisify(child_process.exec);
|
|
247
1224
|
/**
|
|
@@ -315,8 +1292,10 @@ class CLIIntegration {
|
|
|
315
1292
|
const { stdout: authOutput } = await execAsync('onasis auth status --output json 2>/dev/null || lanonasis auth status --output json 2>/dev/null', {
|
|
316
1293
|
timeout: 3000
|
|
317
1294
|
});
|
|
318
|
-
const
|
|
319
|
-
|
|
1295
|
+
const parseResult = safeJsonParse(authOutput);
|
|
1296
|
+
if (parseResult.success) {
|
|
1297
|
+
authenticated = parseResult.data.authenticated === true;
|
|
1298
|
+
}
|
|
320
1299
|
}
|
|
321
1300
|
catch {
|
|
322
1301
|
// Authentication check failed
|
|
@@ -338,10 +1317,10 @@ class CLIIntegration {
|
|
|
338
1317
|
async executeCLICommand(command, options = {}) {
|
|
339
1318
|
const cliInfo = await this.detectCLI();
|
|
340
1319
|
if (!cliInfo.available) {
|
|
341
|
-
return { error: 'CLI not available' };
|
|
1320
|
+
return { error: createErrorResponse('CLI not available', 'API_ERROR') };
|
|
342
1321
|
}
|
|
343
1322
|
if (!cliInfo.authenticated) {
|
|
344
|
-
return { error: 'CLI not authenticated. Run: onasis login' };
|
|
1323
|
+
return { error: createErrorResponse('CLI not authenticated. Run: onasis login', 'AUTH_ERROR', 401) };
|
|
345
1324
|
}
|
|
346
1325
|
try {
|
|
347
1326
|
const timeout = options.timeout || 30000;
|
|
@@ -358,22 +1337,20 @@ class CLIIntegration {
|
|
|
358
1337
|
console.warn('CLI warning:', stderr);
|
|
359
1338
|
}
|
|
360
1339
|
if (outputFormat === 'json') {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return { data:
|
|
364
|
-
}
|
|
365
|
-
catch (parseError) {
|
|
366
|
-
return { error: `Failed to parse CLI JSON output: ${parseError instanceof Error ? parseError.message : 'Unknown error'}` };
|
|
1340
|
+
const parseResult = safeJsonParse(stdout);
|
|
1341
|
+
if (parseResult.success) {
|
|
1342
|
+
return { data: parseResult.data };
|
|
367
1343
|
}
|
|
1344
|
+
return { error: createErrorResponse(parseResult.error, 'VALIDATION_ERROR', 400) };
|
|
368
1345
|
}
|
|
369
1346
|
return { data: stdout };
|
|
370
1347
|
}
|
|
371
1348
|
catch (error) {
|
|
372
1349
|
if (error instanceof Error && error.message.includes('timeout')) {
|
|
373
|
-
return { error: 'CLI command timeout' };
|
|
1350
|
+
return { error: createErrorResponse('CLI command timeout', 'TIMEOUT_ERROR', 408) };
|
|
374
1351
|
}
|
|
375
1352
|
return {
|
|
376
|
-
error: error instanceof Error ? error.message : 'CLI command failed'
|
|
1353
|
+
error: createErrorResponse(error instanceof Error ? error.message : 'CLI command failed', 'API_ERROR')
|
|
377
1354
|
};
|
|
378
1355
|
}
|
|
379
1356
|
}
|
|
@@ -441,14 +1418,14 @@ class CLIIntegration {
|
|
|
441
1418
|
async getMCPStatus() {
|
|
442
1419
|
const cliInfo = await this.detectCLI();
|
|
443
1420
|
if (!cliInfo.mcpAvailable) {
|
|
444
|
-
return { error: 'MCP not available via CLI' };
|
|
1421
|
+
return { error: createErrorResponse('MCP not available via CLI', 'API_ERROR') };
|
|
445
1422
|
}
|
|
446
1423
|
return this.executeCLICommand('mcp status');
|
|
447
1424
|
}
|
|
448
1425
|
async listMCPTools() {
|
|
449
1426
|
const cliInfo = await this.detectCLI();
|
|
450
1427
|
if (!cliInfo.mcpAvailable) {
|
|
451
|
-
return { error: 'MCP not available via CLI' };
|
|
1428
|
+
return { error: createErrorResponse('MCP not available via CLI', 'API_ERROR') };
|
|
452
1429
|
}
|
|
453
1430
|
return this.executeCLICommand('mcp tools');
|
|
454
1431
|
}
|
|
@@ -501,6 +1478,8 @@ class CLIIntegration {
|
|
|
501
1478
|
*
|
|
502
1479
|
* Intelligently routes requests through CLI v1.5.2+ when available,
|
|
503
1480
|
* with fallback to direct API for maximum compatibility and performance
|
|
1481
|
+
*
|
|
1482
|
+
* IMPORTANT: This file uses Node.js-specific features (process.env) and should only be used in Node.js environments
|
|
504
1483
|
*/
|
|
505
1484
|
/**
|
|
506
1485
|
* Enhanced Memory Client with intelligent CLI/API routing
|
|
@@ -516,21 +1495,24 @@ class EnhancedMemoryClient {
|
|
|
516
1495
|
}
|
|
517
1496
|
constructor(config) {
|
|
518
1497
|
this.capabilities = null;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
1498
|
+
// Merge config with defaults, ensuring all required fields are present
|
|
1499
|
+
// Spread config first, then apply defaults only for undefined values
|
|
1500
|
+
const mergedConfig = {
|
|
1501
|
+
...config,
|
|
1502
|
+
preferCLI: config.preferCLI ?? true,
|
|
1503
|
+
enableMCP: config.enableMCP ?? true,
|
|
1504
|
+
cliDetectionTimeout: config.cliDetectionTimeout ?? 5000,
|
|
1505
|
+
fallbackToAPI: config.fallbackToAPI ?? true,
|
|
1506
|
+
minCLIVersion: config.minCLIVersion ?? '1.5.2',
|
|
1507
|
+
verbose: config.verbose ?? false,
|
|
1508
|
+
timeout: config.timeout ?? 30000,
|
|
1509
|
+
apiUrl: config.apiUrl || 'https://api.lanonasis.com',
|
|
528
1510
|
apiKey: config.apiKey || process.env.LANONASIS_API_KEY || '',
|
|
529
1511
|
authToken: config.authToken || '',
|
|
530
|
-
headers: config.headers || {}
|
|
531
|
-
...config
|
|
1512
|
+
headers: config.headers || {}
|
|
532
1513
|
};
|
|
533
|
-
this.
|
|
1514
|
+
this.config = mergedConfig;
|
|
1515
|
+
this.directClient = new CoreMemoryClient(config);
|
|
534
1516
|
this.cliIntegration = new CLIIntegration();
|
|
535
1517
|
}
|
|
536
1518
|
/**
|
|
@@ -625,7 +1607,7 @@ class EnhancedMemoryClient {
|
|
|
625
1607
|
};
|
|
626
1608
|
}
|
|
627
1609
|
return {
|
|
628
|
-
error: error instanceof Error ? error.message : `CLI ${operation} failed`,
|
|
1610
|
+
error: createErrorResponse(error instanceof Error ? error.message : `CLI ${operation} failed`, 'API_ERROR'),
|
|
629
1611
|
source: 'cli',
|
|
630
1612
|
mcpUsed: false
|
|
631
1613
|
};
|
|
@@ -760,7 +1742,7 @@ class EnhancedMemoryClient {
|
|
|
760
1742
|
}
|
|
761
1743
|
catch (error) {
|
|
762
1744
|
return {
|
|
763
|
-
error: error instanceof Error ? error.message : 'Auth status check failed',
|
|
1745
|
+
error: createErrorResponse(error instanceof Error ? error.message : 'Auth status check failed', 'API_ERROR'),
|
|
764
1746
|
source: 'cli',
|
|
765
1747
|
mcpUsed: false
|
|
766
1748
|
};
|
|
@@ -773,7 +1755,7 @@ class EnhancedMemoryClient {
|
|
|
773
1755
|
const capabilities = await this.getCapabilities();
|
|
774
1756
|
if (!capabilities.mcpSupport) {
|
|
775
1757
|
return {
|
|
776
|
-
error: 'MCP not available',
|
|
1758
|
+
error: createErrorResponse('MCP not available', 'API_ERROR'),
|
|
777
1759
|
source: 'cli',
|
|
778
1760
|
mcpUsed: false
|
|
779
1761
|
};
|
|
@@ -784,7 +1766,7 @@ class EnhancedMemoryClient {
|
|
|
784
1766
|
}
|
|
785
1767
|
catch (error) {
|
|
786
1768
|
return {
|
|
787
|
-
error: error instanceof Error ? error.message : 'MCP status check failed',
|
|
1769
|
+
error: createErrorResponse(error instanceof Error ? error.message : 'MCP status check failed', 'API_ERROR'),
|
|
788
1770
|
source: 'cli',
|
|
789
1771
|
mcpUsed: false
|
|
790
1772
|
};
|
|
@@ -824,237 +1806,70 @@ class EnhancedMemoryClient {
|
|
|
824
1806
|
/**
|
|
825
1807
|
* Factory function to create an enhanced memory client
|
|
826
1808
|
*/
|
|
827
|
-
async function
|
|
1809
|
+
async function createNodeMemoryClient(config) {
|
|
828
1810
|
const client = new EnhancedMemoryClient(config);
|
|
829
1811
|
await client.initialize();
|
|
830
1812
|
return client;
|
|
831
1813
|
}
|
|
832
1814
|
|
|
833
1815
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
*
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
isNode: typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node,
|
|
842
|
-
isBrowser: typeof window !== 'undefined',
|
|
843
|
-
isVSCode: typeof globalThis !== 'undefined' && 'vscode' in globalThis,
|
|
844
|
-
isCursor: typeof globalThis !== 'undefined' && 'cursor' in globalThis,
|
|
845
|
-
isWindsurf: typeof globalThis !== 'undefined' && 'windsurf' in globalThis,
|
|
846
|
-
get isIDE() {
|
|
847
|
-
return this.isVSCode || this.isCursor || this.isWindsurf;
|
|
848
|
-
},
|
|
849
|
-
get supportsCLI() {
|
|
850
|
-
return Boolean(this.isNode && !this.isBrowser);
|
|
851
|
-
}
|
|
852
|
-
};
|
|
853
|
-
/**
|
|
854
|
-
* Create smart configuration with environment-aware defaults
|
|
855
|
-
*/
|
|
856
|
-
function createSmartConfig(baseConfig, options = {}) {
|
|
857
|
-
const defaults = {
|
|
858
|
-
preferCLI: Environment.supportsCLI,
|
|
859
|
-
minCLIVersion: '1.5.2',
|
|
860
|
-
enableMCP: true,
|
|
861
|
-
cliDetectionTimeout: 3000,
|
|
862
|
-
verbose: false
|
|
863
|
-
};
|
|
864
|
-
const config = { ...defaults, ...options };
|
|
865
|
-
const preferCLI = config.preferCLI ?? defaults.preferCLI ?? false;
|
|
866
|
-
const minCLIVersion = config.minCLIVersion ?? defaults.minCLIVersion ?? '1.5.2';
|
|
867
|
-
const enableMCP = config.enableMCP ?? defaults.enableMCP ?? true;
|
|
868
|
-
const cliDetectionTimeout = config.cliDetectionTimeout ?? defaults.cliDetectionTimeout ?? 3000;
|
|
869
|
-
const verbose = config.verbose ?? defaults.verbose ?? false;
|
|
870
|
-
return {
|
|
871
|
-
...baseConfig,
|
|
872
|
-
preferCLI,
|
|
873
|
-
minCLIVersion,
|
|
874
|
-
enableMCP,
|
|
875
|
-
cliDetectionTimeout,
|
|
876
|
-
verbose,
|
|
877
|
-
// Smart API configuration with environment detection
|
|
878
|
-
apiUrl: baseConfig.apiUrl || (process?.env?.NODE_ENV === 'development'
|
|
879
|
-
? 'http://localhost:3001'
|
|
880
|
-
: 'https://api.lanonasis.com'),
|
|
881
|
-
// Default timeout based on environment
|
|
882
|
-
timeout: baseConfig.timeout || (Environment.isIDE ? 10000 : 15000)
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Preset configurations for common scenarios
|
|
887
|
-
*/
|
|
888
|
-
const ConfigPresets = {
|
|
889
|
-
/**
|
|
890
|
-
* Development configuration with local API and CLI preference
|
|
891
|
-
*/
|
|
892
|
-
development: (apiKey) => createSmartConfig({
|
|
893
|
-
apiUrl: 'http://localhost:3001',
|
|
894
|
-
apiKey,
|
|
895
|
-
timeout: 30000
|
|
896
|
-
}, {
|
|
897
|
-
preferCLI: true,
|
|
898
|
-
verbose: true
|
|
899
|
-
}),
|
|
900
|
-
/**
|
|
901
|
-
* Production configuration optimized for performance
|
|
902
|
-
*/
|
|
903
|
-
production: (apiKey) => createSmartConfig({
|
|
904
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
905
|
-
apiKey,
|
|
906
|
-
timeout: 15000
|
|
907
|
-
}, {
|
|
908
|
-
preferCLI: Environment.supportsCLI,
|
|
909
|
-
verbose: false
|
|
910
|
-
}),
|
|
911
|
-
/**
|
|
912
|
-
* IDE extension configuration with MCP prioritization
|
|
913
|
-
*/
|
|
914
|
-
ideExtension: (apiKey) => createSmartConfig({
|
|
915
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
916
|
-
apiKey,
|
|
917
|
-
timeout: 10000
|
|
918
|
-
}, {
|
|
919
|
-
preferCLI: true,
|
|
920
|
-
enableMCP: true,
|
|
921
|
-
cliDetectionTimeout: 2000
|
|
922
|
-
}),
|
|
923
|
-
/**
|
|
924
|
-
* Browser-only configuration (no CLI support)
|
|
925
|
-
*/
|
|
926
|
-
browserOnly: (apiKey) => createSmartConfig({
|
|
927
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
928
|
-
apiKey,
|
|
929
|
-
timeout: 15000
|
|
930
|
-
}, {
|
|
931
|
-
preferCLI: false,
|
|
932
|
-
enableMCP: false
|
|
933
|
-
}),
|
|
934
|
-
/**
|
|
935
|
-
* CLI-first configuration for server environments
|
|
936
|
-
*/
|
|
937
|
-
serverCLI: (apiKey) => createSmartConfig({
|
|
938
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
939
|
-
apiKey,
|
|
940
|
-
timeout: 20000
|
|
941
|
-
}, {
|
|
942
|
-
preferCLI: true,
|
|
943
|
-
enableMCP: true,
|
|
944
|
-
verbose: false
|
|
945
|
-
})
|
|
946
|
-
};
|
|
947
|
-
/**
|
|
948
|
-
* Migration helper for existing MemoryClient users
|
|
1816
|
+
* @lanonasis/memory-client/node
|
|
1817
|
+
*
|
|
1818
|
+
* Node.js-enhanced client with CLI integration
|
|
1819
|
+
* ONLY import this in Node.js environments
|
|
1820
|
+
*
|
|
1821
|
+
* Provides intelligent CLI detection and MCP channel utilization
|
|
1822
|
+
* when @lanonasis/cli v1.5.2+ is available
|
|
949
1823
|
*/
|
|
950
|
-
|
|
951
|
-
return createSmartConfig(existingConfig, {
|
|
952
|
-
preferCLI: Environment.supportsCLI,
|
|
953
|
-
...enhancementOptions
|
|
954
|
-
});
|
|
955
|
-
}
|
|
1824
|
+
// Enhanced client with CLI support
|
|
956
1825
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
* Memory status values
|
|
963
|
-
*/
|
|
964
|
-
const MEMORY_STATUSES = ['active', 'archived', 'draft', 'deleted'];
|
|
965
|
-
/**
|
|
966
|
-
* Validation schemas using Zod
|
|
967
|
-
*/
|
|
968
|
-
const createMemorySchema = zod.z.object({
|
|
969
|
-
title: zod.z.string().min(1).max(500),
|
|
970
|
-
content: zod.z.string().min(1).max(50000),
|
|
971
|
-
summary: zod.z.string().max(1000).optional(),
|
|
972
|
-
memory_type: zod.z.enum(MEMORY_TYPES).default('context'),
|
|
973
|
-
topic_id: zod.z.string().uuid().optional(),
|
|
974
|
-
project_ref: zod.z.string().max(100).optional(),
|
|
975
|
-
tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).default([]),
|
|
976
|
-
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
977
|
-
});
|
|
978
|
-
const updateMemorySchema = zod.z.object({
|
|
979
|
-
title: zod.z.string().min(1).max(500).optional(),
|
|
980
|
-
content: zod.z.string().min(1).max(50000).optional(),
|
|
981
|
-
summary: zod.z.string().max(1000).optional(),
|
|
982
|
-
memory_type: zod.z.enum(MEMORY_TYPES).optional(),
|
|
983
|
-
status: zod.z.enum(MEMORY_STATUSES).optional(),
|
|
984
|
-
topic_id: zod.z.string().uuid().nullable().optional(),
|
|
985
|
-
project_ref: zod.z.string().max(100).nullable().optional(),
|
|
986
|
-
tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).optional(),
|
|
987
|
-
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
988
|
-
});
|
|
989
|
-
const searchMemorySchema = zod.z.object({
|
|
990
|
-
query: zod.z.string().min(1).max(1000),
|
|
991
|
-
memory_types: zod.z.array(zod.z.enum(MEMORY_TYPES)).optional(),
|
|
992
|
-
tags: zod.z.array(zod.z.string()).optional(),
|
|
993
|
-
topic_id: zod.z.string().uuid().optional(),
|
|
994
|
-
project_ref: zod.z.string().optional(),
|
|
995
|
-
status: zod.z.enum(MEMORY_STATUSES).default('active'),
|
|
996
|
-
limit: zod.z.number().int().min(1).max(100).default(20),
|
|
997
|
-
threshold: zod.z.number().min(0).max(1).default(0.7)
|
|
998
|
-
});
|
|
999
|
-
const createTopicSchema = zod.z.object({
|
|
1000
|
-
name: zod.z.string().min(1).max(100),
|
|
1001
|
-
description: zod.z.string().max(500).optional(),
|
|
1002
|
-
color: zod.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
1003
|
-
icon: zod.z.string().max(50).optional(),
|
|
1004
|
-
parent_topic_id: zod.z.string().uuid().optional()
|
|
1826
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
1827
|
+
__proto__: null,
|
|
1828
|
+
CLIIntegration: CLIIntegration,
|
|
1829
|
+
EnhancedMemoryClient: EnhancedMemoryClient,
|
|
1830
|
+
createNodeMemoryClient: createNodeMemoryClient
|
|
1005
1831
|
});
|
|
1006
1832
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
* Memory as a Service (MaaS) Client SDK for Lanonasis
|
|
1011
|
-
* Intelligent memory management with semantic search capabilities
|
|
1012
|
-
*/
|
|
1013
|
-
// Main client
|
|
1014
|
-
// Constants
|
|
1015
|
-
const VERSION = '1.0.0';
|
|
1016
|
-
const CLIENT_NAME = '@lanonasis/memory-client';
|
|
1017
|
-
// Environment detection
|
|
1018
|
-
const isBrowser = typeof window !== 'undefined';
|
|
1019
|
-
const isNode = typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node;
|
|
1020
|
-
// Default configurations for different environments
|
|
1021
|
-
const defaultConfigs = {
|
|
1022
|
-
development: {
|
|
1023
|
-
apiUrl: 'http://localhost:3001',
|
|
1024
|
-
timeout: 30000,
|
|
1025
|
-
useGateway: false
|
|
1026
|
-
},
|
|
1027
|
-
production: {
|
|
1028
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
1029
|
-
timeout: 15000,
|
|
1030
|
-
useGateway: true
|
|
1031
|
-
},
|
|
1032
|
-
gateway: {
|
|
1033
|
-
apiUrl: 'https://api.lanonasis.com',
|
|
1034
|
-
timeout: 10000,
|
|
1035
|
-
useGateway: true
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
// Utility functions will be added in a future version to avoid circular imports
|
|
1039
|
-
|
|
1833
|
+
exports.ApiError = ApiError;
|
|
1834
|
+
exports.AuthenticationError = AuthenticationError;
|
|
1835
|
+
exports.CHUNKING_STRATEGIES = CHUNKING_STRATEGIES;
|
|
1040
1836
|
exports.CLIENT_NAME = CLIENT_NAME;
|
|
1041
|
-
exports.
|
|
1042
|
-
exports.
|
|
1043
|
-
exports.
|
|
1044
|
-
exports.Environment = Environment;
|
|
1837
|
+
exports.CONTENT_TYPES = CONTENT_TYPES;
|
|
1838
|
+
exports.CoreMemoryClient = CoreMemoryClient;
|
|
1839
|
+
exports.ERROR_CODES = ERROR_CODES;
|
|
1045
1840
|
exports.MEMORY_STATUSES = MEMORY_STATUSES;
|
|
1046
1841
|
exports.MEMORY_TYPES = MEMORY_TYPES;
|
|
1047
|
-
exports.MemoryClient =
|
|
1842
|
+
exports.MemoryClient = CoreMemoryClient;
|
|
1843
|
+
exports.MemoryClientError = MemoryClientError;
|
|
1844
|
+
exports.NetworkError = NetworkError;
|
|
1845
|
+
exports.NotFoundError = NotFoundError;
|
|
1846
|
+
exports.RateLimitError = RateLimitError;
|
|
1847
|
+
exports.SEARCH_MODES = SEARCH_MODES;
|
|
1848
|
+
exports.ServerError = ServerError;
|
|
1849
|
+
exports.TimeoutError = TimeoutError;
|
|
1048
1850
|
exports.VERSION = VERSION;
|
|
1049
|
-
exports.
|
|
1851
|
+
exports.ValidationError = ValidationError;
|
|
1852
|
+
exports.analyticsDateRangeSchema = analyticsDateRangeSchema;
|
|
1853
|
+
exports.calculateRetryDelay = calculateRetryDelay;
|
|
1854
|
+
exports.createClient = createClient;
|
|
1855
|
+
exports.createErrorFromStatus = createErrorFromStatus;
|
|
1856
|
+
exports.createErrorResponse = createErrorResponse;
|
|
1050
1857
|
exports.createMemoryClient = createMemoryClient;
|
|
1051
1858
|
exports.createMemorySchema = createMemorySchema;
|
|
1052
|
-
exports.createSmartConfig = createSmartConfig;
|
|
1053
1859
|
exports.createTopicSchema = createTopicSchema;
|
|
1054
1860
|
exports.defaultConfigs = defaultConfigs;
|
|
1861
|
+
exports.enhancedSearchSchema = enhancedSearchSchema;
|
|
1862
|
+
exports.getEnvironment = getEnvironment;
|
|
1863
|
+
exports.hasData = hasData;
|
|
1864
|
+
exports.hasError = hasError;
|
|
1865
|
+
exports.httpStatusToErrorCode = httpStatusToErrorCode;
|
|
1866
|
+
exports.isApiErrorResponse = isApiErrorResponse;
|
|
1055
1867
|
exports.isBrowser = isBrowser;
|
|
1868
|
+
exports.isEdge = isEdge;
|
|
1056
1869
|
exports.isNode = isNode;
|
|
1057
|
-
exports.
|
|
1870
|
+
exports.isRetryableError = isRetryableError;
|
|
1871
|
+
exports.preprocessingOptionsSchema = preprocessingOptionsSchema;
|
|
1872
|
+
exports.safeJsonParse = safeJsonParse;
|
|
1058
1873
|
exports.searchMemorySchema = searchMemorySchema;
|
|
1059
1874
|
exports.updateMemorySchema = updateMemorySchema;
|
|
1060
1875
|
//# sourceMappingURL=index.js.map
|