@lanonasis/memory-client 1.0.1 → 2.0.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/index.js CHANGED
@@ -1,22 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var child_process = require('child_process');
4
- var util = require('util');
5
3
  var zod = require('zod');
6
4
 
7
5
  /**
8
- * Memory Client class for interacting with the Memory as a Service API
6
+ * Core Memory Client - Pure Browser-Safe Implementation
7
+ *
8
+ * NO Node.js dependencies, NO CLI code, NO child_process
9
+ * Works in: Browser, React Native, Cloudflare Workers, Edge Functions, Deno, Bun
10
+ *
11
+ * Bundle size: ~15KB gzipped
12
+ */
13
+ /**
14
+ * Core Memory Client class for interacting with the Memory as a Service API
15
+ *
16
+ * This is a pure browser-safe client with zero Node.js dependencies.
17
+ * It uses only standard web APIs (fetch, AbortController, etc.)
9
18
  */
10
- class MemoryClient {
19
+ class CoreMemoryClient {
11
20
  constructor(config) {
12
21
  this.config = {
13
22
  timeout: 30000,
14
- useGateway: true,
15
23
  ...config
16
24
  };
17
25
  this.baseHeaders = {
18
26
  'Content-Type': 'application/json',
19
- 'User-Agent': '@lanonasis/memory-client/1.0.0',
27
+ 'User-Agent': '@lanonasis/memory-client/2.0.0',
20
28
  ...config.headers
21
29
  };
22
30
  // Set authentication headers
@@ -26,11 +34,46 @@ class MemoryClient {
26
34
  else if (config.apiKey) {
27
35
  this.baseHeaders['X-API-Key'] = config.apiKey;
28
36
  }
37
+ // Add organization ID header if provided
38
+ if (config.organizationId) {
39
+ this.baseHeaders['X-Organization-ID'] = config.organizationId;
40
+ }
41
+ }
42
+ /**
43
+ * Enrich request body with organization context if configured
44
+ * This ensures the API has the organization_id even if not in auth token
45
+ */
46
+ enrichWithOrgContext(body) {
47
+ // If organizationId is configured, include it in the request body
48
+ if (this.config.organizationId && !body.organization_id) {
49
+ return {
50
+ ...body,
51
+ organization_id: this.config.organizationId
52
+ };
53
+ }
54
+ // Fallback to userId if no organizationId configured
55
+ if (!this.config.organizationId && this.config.userId && !body.organization_id) {
56
+ return {
57
+ ...body,
58
+ organization_id: this.config.userId
59
+ };
60
+ }
61
+ return body;
29
62
  }
30
63
  /**
31
64
  * Make an HTTP request to the API
32
65
  */
33
66
  async request(endpoint, options = {}) {
67
+ const startTime = Date.now();
68
+ // Call onRequest hook if provided
69
+ if (this.config.onRequest) {
70
+ try {
71
+ this.config.onRequest(endpoint);
72
+ }
73
+ catch (error) {
74
+ console.warn('onRequest hook error:', error);
75
+ }
76
+ }
34
77
  // Handle gateway vs direct API URL formatting
35
78
  const baseUrl = this.config.apiUrl.includes('/api')
36
79
  ? this.config.apiUrl.replace('/api', '')
@@ -54,16 +97,63 @@ class MemoryClient {
54
97
  data = await response.text();
55
98
  }
56
99
  if (!response.ok) {
57
- return {
58
- error: data?.error || `HTTP ${response.status}: ${response.statusText}`
100
+ const error = {
101
+ message: data?.error || `HTTP ${response.status}: ${response.statusText}`,
102
+ statusCode: response.status,
103
+ code: 'API_ERROR'
59
104
  };
105
+ // Call onError hook if provided
106
+ if (this.config.onError) {
107
+ try {
108
+ this.config.onError(error);
109
+ }
110
+ catch (hookError) {
111
+ console.warn('onError hook error:', hookError);
112
+ }
113
+ }
114
+ return { error: error.message };
115
+ }
116
+ // Call onResponse hook if provided
117
+ if (this.config.onResponse) {
118
+ try {
119
+ const duration = Date.now() - startTime;
120
+ this.config.onResponse(endpoint, duration);
121
+ }
122
+ catch (error) {
123
+ console.warn('onResponse hook error:', error);
124
+ }
60
125
  }
61
126
  return { data };
62
127
  }
63
128
  catch (error) {
64
129
  if (error instanceof Error && error.name === 'AbortError') {
130
+ const timeoutError = {
131
+ message: 'Request timeout',
132
+ code: 'TIMEOUT_ERROR',
133
+ statusCode: 408
134
+ };
135
+ if (this.config.onError) {
136
+ try {
137
+ this.config.onError(timeoutError);
138
+ }
139
+ catch (hookError) {
140
+ console.warn('onError hook error:', hookError);
141
+ }
142
+ }
65
143
  return { error: 'Request timeout' };
66
144
  }
145
+ const networkError = {
146
+ message: error instanceof Error ? error.message : 'Network error',
147
+ code: 'NETWORK_ERROR'
148
+ };
149
+ if (this.config.onError) {
150
+ try {
151
+ this.config.onError(networkError);
152
+ }
153
+ catch (hookError) {
154
+ console.warn('onError hook error:', hookError);
155
+ }
156
+ }
67
157
  return {
68
158
  error: error instanceof Error ? error.message : 'Network error'
69
159
  };
@@ -80,9 +170,10 @@ class MemoryClient {
80
170
  * Create a new memory
81
171
  */
82
172
  async createMemory(memory) {
173
+ const enrichedMemory = this.enrichWithOrgContext(memory);
83
174
  return this.request('/memory', {
84
175
  method: 'POST',
85
- body: JSON.stringify(memory)
176
+ body: JSON.stringify(enrichedMemory)
86
177
  });
87
178
  }
88
179
  /**
@@ -131,18 +222,20 @@ class MemoryClient {
131
222
  * Search memories using semantic search
132
223
  */
133
224
  async searchMemories(request) {
225
+ const enrichedRequest = this.enrichWithOrgContext(request);
134
226
  return this.request('/memory/search', {
135
227
  method: 'POST',
136
- body: JSON.stringify(request)
228
+ body: JSON.stringify(enrichedRequest)
137
229
  });
138
230
  }
139
231
  /**
140
232
  * Bulk delete multiple memories
141
233
  */
142
234
  async bulkDeleteMemories(memoryIds) {
235
+ const enrichedRequest = this.enrichWithOrgContext({ memory_ids: memoryIds });
143
236
  return this.request('/memory/bulk/delete', {
144
237
  method: 'POST',
145
- body: JSON.stringify({ memory_ids: memoryIds })
238
+ body: JSON.stringify(enrichedRequest)
146
239
  });
147
240
  }
148
241
  // Topic Operations
@@ -150,9 +243,10 @@ class MemoryClient {
150
243
  * Create a new topic
151
244
  */
152
245
  async createTopic(topic) {
246
+ const enrichedTopic = this.enrichWithOrgContext(topic);
153
247
  return this.request('/topics', {
154
248
  method: 'POST',
155
- body: JSON.stringify(topic)
249
+ body: JSON.stringify(enrichedTopic)
156
250
  });
157
251
  }
158
252
  /**
@@ -231,727 +325,10 @@ class MemoryClient {
231
325
  }
232
326
  }
233
327
  /**
234
- * Factory function to create a new Memory Client instance
328
+ * Factory function to create a new Core Memory Client instance
235
329
  */
236
330
  function createMemoryClient(config) {
237
- return new MemoryClient(config);
238
- }
239
-
240
- /**
241
- * CLI Integration Module for Memory Client SDK
242
- *
243
- * Provides intelligent CLI detection and MCP channel utilization
244
- * when @lanonasis/cli v1.5.2+ is available in the environment
245
- */
246
- const execAsync = util.promisify(child_process.exec);
247
- /**
248
- * CLI Detection and Integration Service
249
- */
250
- class CLIIntegration {
251
- constructor() {
252
- this.cliInfo = null;
253
- this.detectionPromise = null;
254
- }
255
- /**
256
- * Detect if CLI is available and get its capabilities
257
- */
258
- async detectCLI() {
259
- // Return cached result if already detected
260
- if (this.cliInfo) {
261
- return this.cliInfo;
262
- }
263
- // Return existing promise if detection is in progress
264
- if (this.detectionPromise) {
265
- return this.detectionPromise;
266
- }
267
- // Start new detection
268
- this.detectionPromise = this.performDetection();
269
- this.cliInfo = await this.detectionPromise;
270
- return this.cliInfo;
271
- }
272
- async performDetection() {
273
- try {
274
- // Check if onasis/lanonasis CLI is available
275
- let versionOutput = '';
276
- try {
277
- const { stdout } = await execAsync('onasis --version 2>/dev/null', { timeout: 5000 });
278
- versionOutput = stdout;
279
- }
280
- catch {
281
- // Try lanonasis if onasis fails
282
- const { stdout } = await execAsync('lanonasis --version 2>/dev/null', { timeout: 5000 });
283
- versionOutput = stdout;
284
- }
285
- const version = versionOutput.trim();
286
- // Verify it's v1.5.2 or higher for Golden Contract support
287
- const versionMatch = version.match(/(\d+)\.(\d+)\.(\d+)/);
288
- if (!versionMatch) {
289
- return { available: false };
290
- }
291
- const [, major, minor, patch] = versionMatch.map(Number);
292
- const isCompatible = major > 1 || (major === 1 && minor > 5) || (major === 1 && minor === 5 && patch >= 2);
293
- if (!isCompatible) {
294
- return {
295
- available: true,
296
- version,
297
- mcpAvailable: false,
298
- authenticated: false
299
- };
300
- }
301
- // Check MCP availability
302
- let mcpAvailable = false;
303
- try {
304
- await execAsync('onasis mcp status --output json 2>/dev/null || lanonasis mcp status --output json 2>/dev/null', {
305
- timeout: 3000
306
- });
307
- mcpAvailable = true;
308
- }
309
- catch {
310
- // MCP not available or not configured
311
- }
312
- // Check authentication status
313
- let authenticated = false;
314
- try {
315
- const { stdout: authOutput } = await execAsync('onasis auth status --output json 2>/dev/null || lanonasis auth status --output json 2>/dev/null', {
316
- timeout: 3000
317
- });
318
- const authStatus = JSON.parse(authOutput);
319
- authenticated = authStatus.authenticated === true;
320
- }
321
- catch {
322
- // Authentication check failed
323
- }
324
- return {
325
- available: true,
326
- version,
327
- mcpAvailable,
328
- authenticated
329
- };
330
- }
331
- catch {
332
- return { available: false };
333
- }
334
- }
335
- /**
336
- * Execute CLI command and return parsed JSON result
337
- */
338
- async executeCLICommand(command, options = {}) {
339
- const cliInfo = await this.detectCLI();
340
- if (!cliInfo.available) {
341
- return { error: 'CLI not available' };
342
- }
343
- if (!cliInfo.authenticated) {
344
- return { error: 'CLI not authenticated. Run: onasis login' };
345
- }
346
- try {
347
- const timeout = options.timeout || 30000;
348
- const outputFormat = options.outputFormat || 'json';
349
- const verbose = options.verbose ? '--verbose' : '';
350
- // Determine which CLI command to use (prefer onasis for Golden Contract)
351
- const cliCmd = await this.getPreferredCLICommand();
352
- const fullCommand = `${cliCmd} ${command} --output ${outputFormat} ${verbose}`.trim();
353
- const { stdout, stderr } = await execAsync(fullCommand, {
354
- timeout,
355
- maxBuffer: 1024 * 1024 // 1MB buffer
356
- });
357
- if (stderr && stderr.trim()) {
358
- console.warn('CLI warning:', stderr);
359
- }
360
- if (outputFormat === 'json') {
361
- try {
362
- const result = JSON.parse(stdout);
363
- return { data: result };
364
- }
365
- catch (parseError) {
366
- return { error: `Failed to parse CLI JSON output: ${parseError instanceof Error ? parseError.message : 'Unknown error'}` };
367
- }
368
- }
369
- return { data: stdout };
370
- }
371
- catch (error) {
372
- if (error instanceof Error && error.message.includes('timeout')) {
373
- return { error: 'CLI command timeout' };
374
- }
375
- return {
376
- error: error instanceof Error ? error.message : 'CLI command failed'
377
- };
378
- }
379
- }
380
- /**
381
- * Get preferred CLI command (onasis for Golden Contract, fallback to lanonasis)
382
- */
383
- async getPreferredCLICommand() {
384
- try {
385
- child_process.execSync('which onasis', { stdio: 'ignore', timeout: 1000 });
386
- return 'onasis';
387
- }
388
- catch {
389
- return 'lanonasis';
390
- }
391
- }
392
- /**
393
- * Memory operations via CLI
394
- */
395
- async createMemoryViaCLI(title, content, options = {}) {
396
- const { memoryType = 'context', tags = [], topicId } = options;
397
- let command = `memory create --title "${title}" --content "${content}" --memory-type ${memoryType}`;
398
- if (tags.length > 0) {
399
- command += ` --tags "${tags.join(',')}"`;
400
- }
401
- if (topicId) {
402
- command += ` --topic-id "${topicId}"`;
403
- }
404
- return this.executeCLICommand(command);
405
- }
406
- async listMemoriesViaCLI(options = {}) {
407
- let command = 'memory list';
408
- if (options.limit) {
409
- command += ` --limit ${options.limit}`;
410
- }
411
- if (options.memoryType) {
412
- command += ` --memory-type ${options.memoryType}`;
413
- }
414
- if (options.tags && options.tags.length > 0) {
415
- command += ` --tags "${options.tags.join(',')}"`;
416
- }
417
- if (options.sortBy) {
418
- command += ` --sort-by ${options.sortBy}`;
419
- }
420
- return this.executeCLICommand(command);
421
- }
422
- async searchMemoriesViaCLI(query, options = {}) {
423
- let command = `memory search "${query}"`;
424
- if (options.limit) {
425
- command += ` --limit ${options.limit}`;
426
- }
427
- if (options.memoryTypes && options.memoryTypes.length > 0) {
428
- command += ` --memory-types "${options.memoryTypes.join(',')}"`;
429
- }
430
- return this.executeCLICommand(command);
431
- }
432
- /**
433
- * Health check via CLI
434
- */
435
- async healthCheckViaCLI() {
436
- return this.executeCLICommand('health');
437
- }
438
- /**
439
- * MCP-specific operations
440
- */
441
- async getMCPStatus() {
442
- const cliInfo = await this.detectCLI();
443
- if (!cliInfo.mcpAvailable) {
444
- return { error: 'MCP not available via CLI' };
445
- }
446
- return this.executeCLICommand('mcp status');
447
- }
448
- async listMCPTools() {
449
- const cliInfo = await this.detectCLI();
450
- if (!cliInfo.mcpAvailable) {
451
- return { error: 'MCP not available via CLI' };
452
- }
453
- return this.executeCLICommand('mcp tools');
454
- }
455
- /**
456
- * Authentication operations
457
- */
458
- async getAuthStatus() {
459
- return this.executeCLICommand('auth status');
460
- }
461
- /**
462
- * Check if specific CLI features are available
463
- */
464
- async getCapabilities() {
465
- const cliInfo = await this.detectCLI();
466
- return {
467
- cliAvailable: cliInfo.available,
468
- version: cliInfo.version,
469
- mcpSupport: cliInfo.mcpAvailable || false,
470
- authenticated: cliInfo.authenticated || false,
471
- goldenContract: cliInfo.available && this.isGoldenContractCompliant(cliInfo.version)
472
- };
473
- }
474
- isGoldenContractCompliant(version) {
475
- if (!version)
476
- return false;
477
- const versionMatch = version.match(/(\d+)\.(\d+)\.(\d+)/);
478
- if (!versionMatch)
479
- return false;
480
- const [, major, minor, patch] = versionMatch.map(Number);
481
- return major > 1 || (major === 1 && minor > 5) || (major === 1 && minor === 5 && patch >= 2);
482
- }
483
- /**
484
- * Force refresh CLI detection
485
- */
486
- async refresh() {
487
- this.cliInfo = null;
488
- this.detectionPromise = null;
489
- return this.detectCLI();
490
- }
491
- /**
492
- * Get cached CLI info without re-detection
493
- */
494
- getCachedInfo() {
495
- return this.cliInfo;
496
- }
497
- }
498
-
499
- /**
500
- * Enhanced Memory Client with CLI Integration
501
- *
502
- * Intelligently routes requests through CLI v1.5.2+ when available,
503
- * with fallback to direct API for maximum compatibility and performance
504
- */
505
- /**
506
- * Enhanced Memory Client with intelligent CLI/API routing
507
- */
508
- class EnhancedMemoryClient {
509
- createDefaultCapabilities() {
510
- return {
511
- cliAvailable: false,
512
- mcpSupport: false,
513
- authenticated: false,
514
- goldenContract: false
515
- };
516
- }
517
- constructor(config) {
518
- this.capabilities = null;
519
- this.config = {
520
- preferCLI: true,
521
- enableMCP: true,
522
- cliDetectionTimeout: 5000,
523
- fallbackToAPI: true,
524
- minCLIVersion: '1.5.2',
525
- verbose: false,
526
- timeout: 30000,
527
- useGateway: true,
528
- apiKey: config.apiKey || process.env.LANONASIS_API_KEY || '',
529
- authToken: config.authToken || '',
530
- headers: config.headers || {},
531
- ...config
532
- };
533
- this.directClient = new MemoryClient(config);
534
- this.cliIntegration = new CLIIntegration();
535
- }
536
- /**
537
- * Initialize the client and detect capabilities
538
- */
539
- async initialize() {
540
- try {
541
- const detectionPromise = this.cliIntegration.getCapabilities();
542
- const capabilities = this.config.cliDetectionTimeout > 0
543
- ? await Promise.race([
544
- detectionPromise,
545
- new Promise((resolve) => {
546
- setTimeout(() => resolve(null), this.config.cliDetectionTimeout);
547
- })
548
- ])
549
- : await detectionPromise;
550
- if (capabilities) {
551
- this.capabilities = capabilities;
552
- if (this.config.verbose && capabilities.cliAvailable && !capabilities.authenticated) {
553
- const suggestedCommand = capabilities.goldenContract ? 'onasis login' : 'lanonasis login';
554
- console.warn(`CLI detected but not authenticated. Run '${suggestedCommand}' to enable enhanced SDK features.`);
555
- }
556
- }
557
- else {
558
- this.capabilities = this.createDefaultCapabilities();
559
- if (this.config.verbose) {
560
- console.warn(`CLI detection timed out after ${this.config.cliDetectionTimeout}ms. Falling back to API mode.`);
561
- }
562
- }
563
- }
564
- catch (error) {
565
- if (this.config.verbose) {
566
- console.warn('CLI detection failed:', error);
567
- }
568
- this.capabilities = this.createDefaultCapabilities();
569
- }
570
- }
571
- /**
572
- * Get current capabilities
573
- */
574
- async getCapabilities() {
575
- if (!this.capabilities) {
576
- await this.initialize();
577
- }
578
- if (!this.capabilities) {
579
- this.capabilities = this.createDefaultCapabilities();
580
- }
581
- return this.capabilities;
582
- }
583
- /**
584
- * Determine if operation should use CLI
585
- */
586
- async shouldUseCLI() {
587
- const capabilities = await this.getCapabilities();
588
- return (this.config.preferCLI &&
589
- capabilities.cliAvailable &&
590
- capabilities.authenticated &&
591
- capabilities.goldenContract);
592
- }
593
- /**
594
- * Execute operation with intelligent routing
595
- */
596
- async executeOperation(operation, cliOperation, apiOperation) {
597
- const useCLI = await this.shouldUseCLI();
598
- const capabilities = await this.getCapabilities();
599
- if (useCLI) {
600
- try {
601
- const result = await cliOperation();
602
- if (result.error && this.config.fallbackToAPI) {
603
- console.warn(`CLI ${operation} failed, falling back to API:`, result.error);
604
- const apiResult = await apiOperation();
605
- return {
606
- ...apiResult,
607
- source: 'api',
608
- mcpUsed: false
609
- };
610
- }
611
- return {
612
- ...result,
613
- source: 'cli',
614
- mcpUsed: capabilities.mcpSupport
615
- };
616
- }
617
- catch (error) {
618
- if (this.config.fallbackToAPI) {
619
- console.warn(`CLI ${operation} error, falling back to API:`, error);
620
- const apiResult = await apiOperation();
621
- return {
622
- ...apiResult,
623
- source: 'api',
624
- mcpUsed: false
625
- };
626
- }
627
- return {
628
- error: error instanceof Error ? error.message : `CLI ${operation} failed`,
629
- source: 'cli',
630
- mcpUsed: false
631
- };
632
- }
633
- }
634
- else {
635
- const result = await apiOperation();
636
- return {
637
- ...result,
638
- source: 'api',
639
- mcpUsed: false
640
- };
641
- }
642
- }
643
- // Enhanced API Methods
644
- /**
645
- * Health check with intelligent routing
646
- */
647
- async healthCheck() {
648
- return this.executeOperation('health check', () => this.cliIntegration.healthCheckViaCLI(), () => this.directClient.healthCheck());
649
- }
650
- /**
651
- * Create memory with CLI/API routing
652
- */
653
- async createMemory(memory) {
654
- return this.executeOperation('create memory', () => this.cliIntegration.createMemoryViaCLI(memory.title, memory.content, {
655
- memoryType: memory.memory_type,
656
- tags: memory.tags,
657
- topicId: memory.topic_id
658
- }), () => this.directClient.createMemory(memory));
659
- }
660
- /**
661
- * List memories with intelligent routing
662
- */
663
- async listMemories(options = {}) {
664
- return this.executeOperation('list memories', () => this.cliIntegration.listMemoriesViaCLI({
665
- limit: options.limit,
666
- memoryType: options.memory_type,
667
- tags: options.tags,
668
- sortBy: options.sort
669
- }), () => this.directClient.listMemories(options));
670
- }
671
- /**
672
- * Search memories with MCP enhancement when available
673
- */
674
- async searchMemories(request) {
675
- return this.executeOperation('search memories', () => this.cliIntegration.searchMemoriesViaCLI(request.query, {
676
- limit: request.limit,
677
- memoryTypes: request.memory_types
678
- }), () => this.directClient.searchMemories(request));
679
- }
680
- /**
681
- * Get memory by ID (API only for now)
682
- */
683
- async getMemory(id) {
684
- // CLI doesn't have get by ID yet, use API
685
- const result = await this.directClient.getMemory(id);
686
- return {
687
- ...result,
688
- source: 'api',
689
- mcpUsed: false
690
- };
691
- }
692
- /**
693
- * Update memory (API only for now)
694
- */
695
- async updateMemory(id, updates) {
696
- // CLI doesn't have update yet, use API
697
- const result = await this.directClient.updateMemory(id, updates);
698
- return {
699
- ...result,
700
- source: 'api',
701
- mcpUsed: false
702
- };
703
- }
704
- /**
705
- * Delete memory (API only for now)
706
- */
707
- async deleteMemory(id) {
708
- // CLI doesn't have delete yet, use API
709
- const result = await this.directClient.deleteMemory(id);
710
- return {
711
- ...result,
712
- source: 'api',
713
- mcpUsed: false
714
- };
715
- }
716
- // Topic Operations (API only for now)
717
- async createTopic(topic) {
718
- const result = await this.directClient.createTopic(topic);
719
- return { ...result, source: 'api', mcpUsed: false };
720
- }
721
- async getTopics() {
722
- const result = await this.directClient.getTopics();
723
- return { ...result, source: 'api', mcpUsed: false };
724
- }
725
- async getTopic(id) {
726
- const result = await this.directClient.getTopic(id);
727
- return { ...result, source: 'api', mcpUsed: false };
728
- }
729
- async updateTopic(id, updates) {
730
- const result = await this.directClient.updateTopic(id, updates);
731
- return { ...result, source: 'api', mcpUsed: false };
732
- }
733
- async deleteTopic(id) {
734
- const result = await this.directClient.deleteTopic(id);
735
- return { ...result, source: 'api', mcpUsed: false };
736
- }
737
- /**
738
- * Get memory statistics
739
- */
740
- async getMemoryStats() {
741
- const result = await this.directClient.getMemoryStats();
742
- return { ...result, source: 'api', mcpUsed: false };
743
- }
744
- // Utility Methods
745
- /**
746
- * Force CLI re-detection
747
- */
748
- async refreshCLIDetection() {
749
- this.capabilities = null;
750
- await this.cliIntegration.refresh();
751
- await this.initialize();
752
- }
753
- /**
754
- * Get authentication status from CLI
755
- */
756
- async getAuthStatus() {
757
- try {
758
- const result = await this.cliIntegration.getAuthStatus();
759
- return { ...result, source: 'cli', mcpUsed: false };
760
- }
761
- catch (error) {
762
- return {
763
- error: error instanceof Error ? error.message : 'Auth status check failed',
764
- source: 'cli',
765
- mcpUsed: false
766
- };
767
- }
768
- }
769
- /**
770
- * Get MCP status when available
771
- */
772
- async getMCPStatus() {
773
- const capabilities = await this.getCapabilities();
774
- if (!capabilities.mcpSupport) {
775
- return {
776
- error: 'MCP not available',
777
- source: 'cli',
778
- mcpUsed: false
779
- };
780
- }
781
- try {
782
- const result = await this.cliIntegration.getMCPStatus();
783
- return { ...result, source: 'cli', mcpUsed: true };
784
- }
785
- catch (error) {
786
- return {
787
- error: error instanceof Error ? error.message : 'MCP status check failed',
788
- source: 'cli',
789
- mcpUsed: false
790
- };
791
- }
792
- }
793
- /**
794
- * Update authentication for both CLI and API client
795
- */
796
- setAuthToken(token) {
797
- this.directClient.setAuthToken(token);
798
- }
799
- setApiKey(apiKey) {
800
- this.directClient.setApiKey(apiKey);
801
- }
802
- clearAuth() {
803
- this.directClient.clearAuth();
804
- }
805
- /**
806
- * Update configuration
807
- */
808
- updateConfig(updates) {
809
- this.config = { ...this.config, ...updates };
810
- this.directClient.updateConfig(updates);
811
- }
812
- /**
813
- * Get configuration summary
814
- */
815
- getConfigSummary() {
816
- return {
817
- apiUrl: this.config.apiUrl,
818
- preferCLI: this.config.preferCLI,
819
- enableMCP: this.config.enableMCP,
820
- capabilities: this.capabilities || undefined
821
- };
822
- }
823
- }
824
- /**
825
- * Factory function to create an enhanced memory client
826
- */
827
- async function createEnhancedMemoryClient(config) {
828
- const client = new EnhancedMemoryClient(config);
829
- await client.initialize();
830
- return client;
831
- }
832
-
833
- /**
834
- * Configuration utilities for Memory Client SDK
835
- * Provides smart defaults and environment detection for CLI/MCP integration
836
- */
837
- /**
838
- * Environment detection utilities
839
- */
840
- const Environment = {
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
949
- */
950
- function migrateToEnhanced(existingConfig, enhancementOptions = {}) {
951
- return createSmartConfig(existingConfig, {
952
- preferCLI: Environment.supportsCLI,
953
- ...enhancementOptions
954
- });
331
+ return new CoreMemoryClient(config);
955
332
  }
956
333
 
957
334
  /**
@@ -1004,57 +381,257 @@ const createTopicSchema = zod.z.object({
1004
381
  parent_topic_id: zod.z.string().uuid().optional()
1005
382
  });
1006
383
 
384
+ /**
385
+ * Error handling for Memory Client
386
+ * Browser-safe, no Node.js dependencies
387
+ */
388
+ /**
389
+ * Base error class for Memory Client errors
390
+ */
391
+ class MemoryClientError extends Error {
392
+ constructor(message, code, statusCode, details) {
393
+ super(message);
394
+ this.code = code;
395
+ this.statusCode = statusCode;
396
+ this.details = details;
397
+ this.name = 'MemoryClientError';
398
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
399
+ if (Error.captureStackTrace) {
400
+ Error.captureStackTrace(this, MemoryClientError);
401
+ }
402
+ }
403
+ }
404
+ /**
405
+ * Network/API error
406
+ */
407
+ class ApiError extends MemoryClientError {
408
+ constructor(message, statusCode, details) {
409
+ super(message, 'API_ERROR', statusCode, details);
410
+ this.name = 'ApiError';
411
+ }
412
+ }
413
+ /**
414
+ * Authentication error
415
+ */
416
+ class AuthenticationError extends MemoryClientError {
417
+ constructor(message = 'Authentication required') {
418
+ super(message, 'AUTH_ERROR', 401);
419
+ this.name = 'AuthenticationError';
420
+ }
421
+ }
422
+ /**
423
+ * Validation error
424
+ */
425
+ class ValidationError extends MemoryClientError {
426
+ constructor(message, details) {
427
+ super(message, 'VALIDATION_ERROR', 400, details);
428
+ this.name = 'ValidationError';
429
+ }
430
+ }
431
+ /**
432
+ * Timeout error
433
+ */
434
+ class TimeoutError extends MemoryClientError {
435
+ constructor(message = 'Request timeout') {
436
+ super(message, 'TIMEOUT_ERROR', 408);
437
+ this.name = 'TimeoutError';
438
+ }
439
+ }
440
+ /**
441
+ * Rate limit error
442
+ */
443
+ class RateLimitError extends MemoryClientError {
444
+ constructor(message = 'Rate limit exceeded') {
445
+ super(message, 'RATE_LIMIT_ERROR', 429);
446
+ this.name = 'RateLimitError';
447
+ }
448
+ }
449
+ /**
450
+ * Not found error
451
+ */
452
+ class NotFoundError extends MemoryClientError {
453
+ constructor(resource) {
454
+ super(`${resource} not found`, 'NOT_FOUND', 404);
455
+ this.name = 'NotFoundError';
456
+ }
457
+ }
458
+
1007
459
  /**
1008
460
  * @lanonasis/memory-client
1009
461
  *
1010
- * Memory as a Service (MaaS) Client SDK for Lanonasis
462
+ * Universal Memory as a Service (MaaS) Client SDK for Lanonasis
1011
463
  * Intelligent memory management with semantic search capabilities
464
+ *
465
+ * v2.0.0 - Universal SDK Redesign
466
+ * "Drop In and Sleep" Architecture - Works everywhere with zero configuration
467
+ *
468
+ * @example Browser/Web App
469
+ * ```ts
470
+ * import { createMemoryClient } from '@lanonasis/memory-client/core';
471
+ * const client = createMemoryClient({ apiKey: 'your-key' });
472
+ * ```
473
+ *
474
+ * @example Node.js
475
+ * ```ts
476
+ * import { createNodeMemoryClient } from '@lanonasis/memory-client/node';
477
+ * const client = await createNodeMemoryClient({ apiKey: process.env.KEY });
478
+ * ```
479
+ *
480
+ * @example React
481
+ * ```tsx
482
+ * import { MemoryProvider, useMemories } from '@lanonasis/memory-client/react';
483
+ * ```
484
+ *
485
+ * @example Vue
486
+ * ```ts
487
+ * import { createMemoryPlugin, useMemories } from '@lanonasis/memory-client/vue';
488
+ * ```
1012
489
  */
1013
- // Main client
490
+ // ========================================
491
+ // Core Exports (Browser-Safe)
492
+ // ========================================
493
+ // ========================================
1014
494
  // Constants
1015
- const VERSION = '1.0.0';
495
+ // ========================================
496
+ const VERSION = '2.0.0';
1016
497
  const CLIENT_NAME = '@lanonasis/memory-client';
1017
- // Environment detection
498
+ // ========================================
499
+ // Environment Detection
500
+ // ========================================
1018
501
  const isBrowser = typeof window !== 'undefined';
1019
502
  const isNode = typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node;
1020
- // Default configurations for different environments
503
+ // ========================================
504
+ // Default Configurations
505
+ // ========================================
1021
506
  const defaultConfigs = {
1022
507
  development: {
1023
508
  apiUrl: 'http://localhost:3001',
1024
509
  timeout: 30000,
1025
- useGateway: false
1026
510
  },
1027
511
  production: {
1028
512
  apiUrl: 'https://api.lanonasis.com',
1029
513
  timeout: 15000,
1030
- useGateway: true
1031
514
  },
1032
- gateway: {
515
+ edge: {
1033
516
  apiUrl: 'https://api.lanonasis.com',
1034
- timeout: 10000,
1035
- useGateway: true
517
+ timeout: 5000,
1036
518
  }
1037
519
  };
1038
- // Utility functions will be added in a future version to avoid circular imports
520
+ // Note: Enhanced client requires Node.js, so we don't export it from main entry
521
+ // Users should import from '@lanonasis/memory-client/node' instead
522
+ // ========================================
523
+ // Usage Instructions
524
+ // ========================================
525
+ /**
526
+ * # @lanonasis/memory-client v2.0
527
+ *
528
+ * ## Quick Start
529
+ *
530
+ * ### Browser / Web App
531
+ * ```bash
532
+ * npm install @lanonasis/memory-client
533
+ * ```
534
+ * ```typescript
535
+ * import { createMemoryClient } from '@lanonasis/memory-client/core';
536
+ *
537
+ * const client = createMemoryClient({
538
+ * apiUrl: 'https://api.lanonasis.com',
539
+ * apiKey: 'your-key-here'
540
+ * });
541
+ *
542
+ * const memories = await client.listMemories();
543
+ * ```
544
+ *
545
+ * ### Node.js with CLI Support
546
+ * ```typescript
547
+ * import { createNodeMemoryClient } from '@lanonasis/memory-client/node';
548
+ *
549
+ * const client = await createNodeMemoryClient({
550
+ * apiKey: process.env.LANONASIS_KEY,
551
+ * preferCLI: true // Automatically uses CLI if available
552
+ * });
553
+ *
554
+ * const result = await client.listMemories();
555
+ * console.log(`Using: ${result.source}`); // 'cli' or 'api'
556
+ * ```
557
+ *
558
+ * ### React
559
+ * ```tsx
560
+ * import { MemoryProvider, useMemories } from '@lanonasis/memory-client/react';
561
+ *
562
+ * function App() {
563
+ * return (
564
+ * <MemoryProvider apiKey="your-key">
565
+ * <MemoryList />
566
+ * </MemoryProvider>
567
+ * );
568
+ * }
569
+ *
570
+ * function MemoryList() {
571
+ * const { memories, loading } = useMemories();
572
+ * if (loading) return <div>Loading...</div>;
573
+ * return <div>{memories.map(m => <div key={m.id}>{m.title}</div>)}</div>;
574
+ * }
575
+ * ```
576
+ *
577
+ * ### Vue 3
578
+ * ```typescript
579
+ * import { createMemoryPlugin, useMemories } from '@lanonasis/memory-client/vue';
580
+ *
581
+ * const app = createApp(App);
582
+ * app.use(createMemoryPlugin({ apiKey: 'your-key' }));
583
+ * ```
584
+ *
585
+ * ### Edge Functions (Cloudflare Workers, Vercel Edge)
586
+ * ```typescript
587
+ * import { createMemoryClient } from '@lanonasis/memory-client/core';
588
+ * import { edgePreset } from '@lanonasis/memory-client/presets';
589
+ *
590
+ * export default {
591
+ * async fetch(request: Request, env: Env) {
592
+ * const client = createMemoryClient(edgePreset({
593
+ * apiKey: env.LANONASIS_KEY
594
+ * }));
595
+ * const memories = await client.searchMemories({ query: 'test' });
596
+ * return Response.json(memories.data);
597
+ * }
598
+ * };
599
+ * ```
600
+ *
601
+ * ## Bundle Sizes
602
+ *
603
+ * - **Core** (browser): ~15KB gzipped
604
+ * - **Node** (with CLI): ~35KB gzipped
605
+ * - **React**: ~18KB gzipped (+ React)
606
+ * - **Vue**: ~17KB gzipped (+ Vue)
607
+ * - **Presets**: ~2KB gzipped
608
+ *
609
+ * ## Documentation
610
+ *
611
+ * - Full docs: https://docs.lanonasis.com/sdk
612
+ * - API reference: https://docs.lanonasis.com/api
613
+ * - Examples: https://github.com/lanonasis/examples
614
+ */
1039
615
 
616
+ exports.ApiErrorClass = ApiError;
617
+ exports.AuthenticationError = AuthenticationError;
1040
618
  exports.CLIENT_NAME = CLIENT_NAME;
1041
- exports.CLIIntegration = CLIIntegration;
1042
- exports.ConfigPresets = ConfigPresets;
1043
- exports.EnhancedMemoryClient = EnhancedMemoryClient;
1044
- exports.Environment = Environment;
619
+ exports.CoreMemoryClient = CoreMemoryClient;
1045
620
  exports.MEMORY_STATUSES = MEMORY_STATUSES;
1046
621
  exports.MEMORY_TYPES = MEMORY_TYPES;
1047
- exports.MemoryClient = MemoryClient;
622
+ exports.MemoryClient = CoreMemoryClient;
623
+ exports.MemoryClientError = MemoryClientError;
624
+ exports.NotFoundError = NotFoundError;
625
+ exports.RateLimitError = RateLimitError;
626
+ exports.TimeoutError = TimeoutError;
1048
627
  exports.VERSION = VERSION;
1049
- exports.createEnhancedMemoryClient = createEnhancedMemoryClient;
628
+ exports.ValidationError = ValidationError;
1050
629
  exports.createMemoryClient = createMemoryClient;
1051
630
  exports.createMemorySchema = createMemorySchema;
1052
- exports.createSmartConfig = createSmartConfig;
1053
631
  exports.createTopicSchema = createTopicSchema;
1054
632
  exports.defaultConfigs = defaultConfigs;
1055
633
  exports.isBrowser = isBrowser;
1056
634
  exports.isNode = isNode;
1057
- exports.migrateToEnhanced = migrateToEnhanced;
1058
635
  exports.searchMemorySchema = searchMemorySchema;
1059
636
  exports.updateMemorySchema = updateMemorySchema;
1060
637
  //# sourceMappingURL=index.js.map