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