@lanonasis/memory-client 1.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 ADDED
@@ -0,0 +1,1052 @@
1
+ 'use strict';
2
+
3
+ var child_process = require('child_process');
4
+ var util = require('util');
5
+ var zod = require('zod');
6
+
7
+ /**
8
+ * Memory Client class for interacting with the Memory as a Service API
9
+ */
10
+ class MemoryClient {
11
+ constructor(config) {
12
+ this.config = {
13
+ timeout: 30000,
14
+ useGateway: true,
15
+ ...config
16
+ };
17
+ this.baseHeaders = {
18
+ 'Content-Type': 'application/json',
19
+ 'User-Agent': '@lanonasis/memory-client/1.0.0',
20
+ ...config.headers
21
+ };
22
+ // Set authentication headers
23
+ if (config.authToken) {
24
+ this.baseHeaders['Authorization'] = `Bearer ${config.authToken}`;
25
+ }
26
+ else if (config.apiKey) {
27
+ this.baseHeaders['X-API-Key'] = config.apiKey;
28
+ }
29
+ }
30
+ /**
31
+ * Make an HTTP request to the API
32
+ */
33
+ async request(endpoint, options = {}) {
34
+ // Handle gateway vs direct API URL formatting
35
+ const baseUrl = this.config.apiUrl.includes('/api')
36
+ ? this.config.apiUrl.replace('/api', '')
37
+ : this.config.apiUrl;
38
+ const url = `${baseUrl}/api/v1${endpoint}`;
39
+ try {
40
+ const controller = new AbortController();
41
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
42
+ const response = await fetch(url, {
43
+ headers: { ...this.baseHeaders, ...options.headers },
44
+ signal: controller.signal,
45
+ ...options,
46
+ });
47
+ clearTimeout(timeoutId);
48
+ let data;
49
+ const contentType = response.headers.get('content-type');
50
+ if (contentType && contentType.includes('application/json')) {
51
+ data = await response.json();
52
+ }
53
+ else {
54
+ data = await response.text();
55
+ }
56
+ if (!response.ok) {
57
+ return {
58
+ error: data?.error || `HTTP ${response.status}: ${response.statusText}`
59
+ };
60
+ }
61
+ return { data };
62
+ }
63
+ catch (error) {
64
+ if (error instanceof Error && error.name === 'AbortError') {
65
+ return { error: 'Request timeout' };
66
+ }
67
+ return {
68
+ error: error instanceof Error ? error.message : 'Network error'
69
+ };
70
+ }
71
+ }
72
+ /**
73
+ * Test the API connection and authentication
74
+ */
75
+ async healthCheck() {
76
+ return this.request('/health');
77
+ }
78
+ // Memory Operations
79
+ /**
80
+ * Create a new memory
81
+ */
82
+ async createMemory(memory) {
83
+ return this.request('/memory', {
84
+ method: 'POST',
85
+ body: JSON.stringify(memory)
86
+ });
87
+ }
88
+ /**
89
+ * Get a memory by ID
90
+ */
91
+ async getMemory(id) {
92
+ return this.request(`/memory/${encodeURIComponent(id)}`);
93
+ }
94
+ /**
95
+ * Update an existing memory
96
+ */
97
+ async updateMemory(id, updates) {
98
+ return this.request(`/memory/${encodeURIComponent(id)}`, {
99
+ method: 'PUT',
100
+ body: JSON.stringify(updates)
101
+ });
102
+ }
103
+ /**
104
+ * Delete a memory
105
+ */
106
+ async deleteMemory(id) {
107
+ return this.request(`/memory/${encodeURIComponent(id)}`, {
108
+ method: 'DELETE'
109
+ });
110
+ }
111
+ /**
112
+ * List memories with optional filtering and pagination
113
+ */
114
+ async listMemories(options = {}) {
115
+ const params = new URLSearchParams();
116
+ Object.entries(options).forEach(([key, value]) => {
117
+ if (value !== undefined && value !== null) {
118
+ if (Array.isArray(value)) {
119
+ params.append(key, value.join(','));
120
+ }
121
+ else {
122
+ params.append(key, String(value));
123
+ }
124
+ }
125
+ });
126
+ const queryString = params.toString();
127
+ const endpoint = queryString ? `/memory?${queryString}` : '/memory';
128
+ return this.request(endpoint);
129
+ }
130
+ /**
131
+ * Search memories using semantic search
132
+ */
133
+ async searchMemories(request) {
134
+ return this.request('/memory/search', {
135
+ method: 'POST',
136
+ body: JSON.stringify(request)
137
+ });
138
+ }
139
+ /**
140
+ * Bulk delete multiple memories
141
+ */
142
+ async bulkDeleteMemories(memoryIds) {
143
+ return this.request('/memory/bulk/delete', {
144
+ method: 'POST',
145
+ body: JSON.stringify({ memory_ids: memoryIds })
146
+ });
147
+ }
148
+ // Topic Operations
149
+ /**
150
+ * Create a new topic
151
+ */
152
+ async createTopic(topic) {
153
+ return this.request('/topics', {
154
+ method: 'POST',
155
+ body: JSON.stringify(topic)
156
+ });
157
+ }
158
+ /**
159
+ * Get all topics
160
+ */
161
+ async getTopics() {
162
+ return this.request('/topics');
163
+ }
164
+ /**
165
+ * Get a topic by ID
166
+ */
167
+ async getTopic(id) {
168
+ return this.request(`/topics/${encodeURIComponent(id)}`);
169
+ }
170
+ /**
171
+ * Update a topic
172
+ */
173
+ async updateTopic(id, updates) {
174
+ return this.request(`/topics/${encodeURIComponent(id)}`, {
175
+ method: 'PUT',
176
+ body: JSON.stringify(updates)
177
+ });
178
+ }
179
+ /**
180
+ * Delete a topic
181
+ */
182
+ async deleteTopic(id) {
183
+ return this.request(`/topics/${encodeURIComponent(id)}`, {
184
+ method: 'DELETE'
185
+ });
186
+ }
187
+ /**
188
+ * Get user memory statistics
189
+ */
190
+ async getMemoryStats() {
191
+ return this.request('/memory/stats');
192
+ }
193
+ // Utility Methods
194
+ /**
195
+ * Update authentication token
196
+ */
197
+ setAuthToken(token) {
198
+ this.baseHeaders['Authorization'] = `Bearer ${token}`;
199
+ delete this.baseHeaders['X-API-Key'];
200
+ }
201
+ /**
202
+ * Update API key
203
+ */
204
+ setApiKey(apiKey) {
205
+ this.baseHeaders['X-API-Key'] = apiKey;
206
+ delete this.baseHeaders['Authorization'];
207
+ }
208
+ /**
209
+ * Clear authentication
210
+ */
211
+ clearAuth() {
212
+ delete this.baseHeaders['Authorization'];
213
+ delete this.baseHeaders['X-API-Key'];
214
+ }
215
+ /**
216
+ * Update configuration
217
+ */
218
+ updateConfig(updates) {
219
+ this.config = { ...this.config, ...updates };
220
+ if (updates.headers) {
221
+ this.baseHeaders = { ...this.baseHeaders, ...updates.headers };
222
+ }
223
+ }
224
+ /**
225
+ * Get current configuration (excluding sensitive data)
226
+ */
227
+ getConfig() {
228
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
229
+ const { apiKey, authToken, ...safeConfig } = this.config;
230
+ return safeConfig;
231
+ }
232
+ }
233
+ /**
234
+ * Factory function to create a new Memory Client instance
235
+ */
236
+ 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
+ return this.capabilities;
579
+ }
580
+ /**
581
+ * Determine if operation should use CLI
582
+ */
583
+ async shouldUseCLI() {
584
+ const capabilities = await this.getCapabilities();
585
+ return (this.config.preferCLI &&
586
+ capabilities.cliAvailable &&
587
+ capabilities.authenticated &&
588
+ capabilities.goldenContract);
589
+ }
590
+ /**
591
+ * Execute operation with intelligent routing
592
+ */
593
+ async executeOperation(operation, cliOperation, apiOperation) {
594
+ const useCLI = await this.shouldUseCLI();
595
+ const capabilities = await this.getCapabilities();
596
+ if (useCLI) {
597
+ try {
598
+ const result = await cliOperation();
599
+ if (result.error && this.config.fallbackToAPI) {
600
+ console.warn(`CLI ${operation} failed, falling back to API:`, result.error);
601
+ const apiResult = await apiOperation();
602
+ return {
603
+ ...apiResult,
604
+ source: 'api',
605
+ mcpUsed: false
606
+ };
607
+ }
608
+ return {
609
+ ...result,
610
+ source: 'cli',
611
+ mcpUsed: capabilities.mcpSupport
612
+ };
613
+ }
614
+ catch (error) {
615
+ if (this.config.fallbackToAPI) {
616
+ console.warn(`CLI ${operation} error, falling back to API:`, error);
617
+ const apiResult = await apiOperation();
618
+ return {
619
+ ...apiResult,
620
+ source: 'api',
621
+ mcpUsed: false
622
+ };
623
+ }
624
+ return {
625
+ error: error instanceof Error ? error.message : `CLI ${operation} failed`,
626
+ source: 'cli',
627
+ mcpUsed: false
628
+ };
629
+ }
630
+ }
631
+ else {
632
+ const result = await apiOperation();
633
+ return {
634
+ ...result,
635
+ source: 'api',
636
+ mcpUsed: false
637
+ };
638
+ }
639
+ }
640
+ // Enhanced API Methods
641
+ /**
642
+ * Health check with intelligent routing
643
+ */
644
+ async healthCheck() {
645
+ return this.executeOperation('health check', () => this.cliIntegration.healthCheckViaCLI(), () => this.directClient.healthCheck());
646
+ }
647
+ /**
648
+ * Create memory with CLI/API routing
649
+ */
650
+ async createMemory(memory) {
651
+ return this.executeOperation('create memory', () => this.cliIntegration.createMemoryViaCLI(memory.title, memory.content, {
652
+ memoryType: memory.memory_type,
653
+ tags: memory.tags,
654
+ topicId: memory.topic_id
655
+ }), () => this.directClient.createMemory(memory));
656
+ }
657
+ /**
658
+ * List memories with intelligent routing
659
+ */
660
+ async listMemories(options = {}) {
661
+ return this.executeOperation('list memories', () => this.cliIntegration.listMemoriesViaCLI({
662
+ limit: options.limit,
663
+ memoryType: options.memory_type,
664
+ tags: options.tags,
665
+ sortBy: options.sort
666
+ }), () => this.directClient.listMemories(options));
667
+ }
668
+ /**
669
+ * Search memories with MCP enhancement when available
670
+ */
671
+ async searchMemories(request) {
672
+ return this.executeOperation('search memories', () => this.cliIntegration.searchMemoriesViaCLI(request.query, {
673
+ limit: request.limit,
674
+ memoryTypes: request.memory_types
675
+ }), () => this.directClient.searchMemories(request));
676
+ }
677
+ /**
678
+ * Get memory by ID (API only for now)
679
+ */
680
+ async getMemory(id) {
681
+ // CLI doesn't have get by ID yet, use API
682
+ const result = await this.directClient.getMemory(id);
683
+ return {
684
+ ...result,
685
+ source: 'api',
686
+ mcpUsed: false
687
+ };
688
+ }
689
+ /**
690
+ * Update memory (API only for now)
691
+ */
692
+ async updateMemory(id, updates) {
693
+ // CLI doesn't have update yet, use API
694
+ const result = await this.directClient.updateMemory(id, updates);
695
+ return {
696
+ ...result,
697
+ source: 'api',
698
+ mcpUsed: false
699
+ };
700
+ }
701
+ /**
702
+ * Delete memory (API only for now)
703
+ */
704
+ async deleteMemory(id) {
705
+ // CLI doesn't have delete yet, use API
706
+ const result = await this.directClient.deleteMemory(id);
707
+ return {
708
+ ...result,
709
+ source: 'api',
710
+ mcpUsed: false
711
+ };
712
+ }
713
+ // Topic Operations (API only for now)
714
+ async createTopic(topic) {
715
+ const result = await this.directClient.createTopic(topic);
716
+ return { ...result, source: 'api', mcpUsed: false };
717
+ }
718
+ async getTopics() {
719
+ const result = await this.directClient.getTopics();
720
+ return { ...result, source: 'api', mcpUsed: false };
721
+ }
722
+ async getTopic(id) {
723
+ const result = await this.directClient.getTopic(id);
724
+ return { ...result, source: 'api', mcpUsed: false };
725
+ }
726
+ async updateTopic(id, updates) {
727
+ const result = await this.directClient.updateTopic(id, updates);
728
+ return { ...result, source: 'api', mcpUsed: false };
729
+ }
730
+ async deleteTopic(id) {
731
+ const result = await this.directClient.deleteTopic(id);
732
+ return { ...result, source: 'api', mcpUsed: false };
733
+ }
734
+ /**
735
+ * Get memory statistics
736
+ */
737
+ async getMemoryStats() {
738
+ const result = await this.directClient.getMemoryStats();
739
+ return { ...result, source: 'api', mcpUsed: false };
740
+ }
741
+ // Utility Methods
742
+ /**
743
+ * Force CLI re-detection
744
+ */
745
+ async refreshCLIDetection() {
746
+ this.capabilities = null;
747
+ await this.cliIntegration.refresh();
748
+ await this.initialize();
749
+ }
750
+ /**
751
+ * Get authentication status from CLI
752
+ */
753
+ async getAuthStatus() {
754
+ try {
755
+ const result = await this.cliIntegration.getAuthStatus();
756
+ return { ...result, source: 'cli', mcpUsed: false };
757
+ }
758
+ catch (error) {
759
+ return {
760
+ error: error instanceof Error ? error.message : 'Auth status check failed',
761
+ source: 'cli',
762
+ mcpUsed: false
763
+ };
764
+ }
765
+ }
766
+ /**
767
+ * Get MCP status when available
768
+ */
769
+ async getMCPStatus() {
770
+ const capabilities = await this.getCapabilities();
771
+ if (!capabilities.mcpSupport) {
772
+ return {
773
+ error: 'MCP not available',
774
+ source: 'cli',
775
+ mcpUsed: false
776
+ };
777
+ }
778
+ try {
779
+ const result = await this.cliIntegration.getMCPStatus();
780
+ return { ...result, source: 'cli', mcpUsed: true };
781
+ }
782
+ catch (error) {
783
+ return {
784
+ error: error instanceof Error ? error.message : 'MCP status check failed',
785
+ source: 'cli',
786
+ mcpUsed: false
787
+ };
788
+ }
789
+ }
790
+ /**
791
+ * Update authentication for both CLI and API client
792
+ */
793
+ setAuthToken(token) {
794
+ this.directClient.setAuthToken(token);
795
+ }
796
+ setApiKey(apiKey) {
797
+ this.directClient.setApiKey(apiKey);
798
+ }
799
+ clearAuth() {
800
+ this.directClient.clearAuth();
801
+ }
802
+ /**
803
+ * Update configuration
804
+ */
805
+ updateConfig(updates) {
806
+ this.config = { ...this.config, ...updates };
807
+ this.directClient.updateConfig(updates);
808
+ }
809
+ /**
810
+ * Get configuration summary
811
+ */
812
+ getConfigSummary() {
813
+ return {
814
+ apiUrl: this.config.apiUrl,
815
+ preferCLI: this.config.preferCLI,
816
+ enableMCP: this.config.enableMCP,
817
+ capabilities: this.capabilities || undefined
818
+ };
819
+ }
820
+ }
821
+ /**
822
+ * Factory function to create an enhanced memory client
823
+ */
824
+ async function createEnhancedMemoryClient(config) {
825
+ const client = new EnhancedMemoryClient(config);
826
+ await client.initialize();
827
+ return client;
828
+ }
829
+
830
+ /**
831
+ * Configuration utilities for Memory Client SDK
832
+ * Provides smart defaults and environment detection for CLI/MCP integration
833
+ */
834
+ /**
835
+ * Environment detection utilities
836
+ */
837
+ const Environment = {
838
+ isNode: typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node,
839
+ isBrowser: typeof window !== 'undefined',
840
+ isVSCode: typeof globalThis !== 'undefined' && 'vscode' in globalThis,
841
+ isCursor: typeof globalThis !== 'undefined' && 'cursor' in globalThis,
842
+ isWindsurf: typeof globalThis !== 'undefined' && 'windsurf' in globalThis,
843
+ get isIDE() {
844
+ return this.isVSCode || this.isCursor || this.isWindsurf;
845
+ },
846
+ get supportsCLI() {
847
+ return Boolean(this.isNode && !this.isBrowser);
848
+ }
849
+ };
850
+ /**
851
+ * Create smart configuration with environment-aware defaults
852
+ */
853
+ function createSmartConfig(baseConfig, options = {}) {
854
+ const defaults = {
855
+ preferCLI: Environment.supportsCLI,
856
+ minCLIVersion: '1.5.2',
857
+ enableMCP: true,
858
+ cliDetectionTimeout: 3000,
859
+ verbose: false
860
+ };
861
+ const config = { ...defaults, ...options };
862
+ return {
863
+ ...baseConfig,
864
+ preferCLI: config.preferCLI,
865
+ minCLIVersion: config.minCLIVersion,
866
+ enableMCP: config.enableMCP,
867
+ cliDetectionTimeout: config.cliDetectionTimeout,
868
+ verbose: config.verbose,
869
+ // Smart API configuration with environment detection
870
+ apiUrl: baseConfig.apiUrl || (process?.env?.NODE_ENV === 'development'
871
+ ? 'http://localhost:3001'
872
+ : 'https://api.lanonasis.com'),
873
+ // Default timeout based on environment
874
+ timeout: baseConfig.timeout || (Environment.isIDE ? 10000 : 15000)
875
+ };
876
+ }
877
+ /**
878
+ * Preset configurations for common scenarios
879
+ */
880
+ const ConfigPresets = {
881
+ /**
882
+ * Development configuration with local API and CLI preference
883
+ */
884
+ development: (apiKey) => createSmartConfig({
885
+ apiUrl: 'http://localhost:3001',
886
+ apiKey,
887
+ timeout: 30000
888
+ }, {
889
+ preferCLI: true,
890
+ verbose: true
891
+ }),
892
+ /**
893
+ * Production configuration optimized for performance
894
+ */
895
+ production: (apiKey) => createSmartConfig({
896
+ apiUrl: 'https://api.lanonasis.com',
897
+ apiKey,
898
+ timeout: 15000
899
+ }, {
900
+ preferCLI: Environment.supportsCLI,
901
+ verbose: false
902
+ }),
903
+ /**
904
+ * IDE extension configuration with MCP prioritization
905
+ */
906
+ ideExtension: (apiKey) => createSmartConfig({
907
+ apiUrl: 'https://api.lanonasis.com',
908
+ apiKey,
909
+ timeout: 10000
910
+ }, {
911
+ preferCLI: true,
912
+ enableMCP: true,
913
+ cliDetectionTimeout: 2000
914
+ }),
915
+ /**
916
+ * Browser-only configuration (no CLI support)
917
+ */
918
+ browserOnly: (apiKey) => createSmartConfig({
919
+ apiUrl: 'https://api.lanonasis.com',
920
+ apiKey,
921
+ timeout: 15000
922
+ }, {
923
+ preferCLI: false,
924
+ enableMCP: false
925
+ }),
926
+ /**
927
+ * CLI-first configuration for server environments
928
+ */
929
+ serverCLI: (apiKey) => createSmartConfig({
930
+ apiUrl: 'https://api.lanonasis.com',
931
+ apiKey,
932
+ timeout: 20000
933
+ }, {
934
+ preferCLI: true,
935
+ enableMCP: true,
936
+ verbose: false
937
+ })
938
+ };
939
+ /**
940
+ * Migration helper for existing MemoryClient users
941
+ */
942
+ function migrateToEnhanced(existingConfig, enhancementOptions = {}) {
943
+ return createSmartConfig(existingConfig, {
944
+ preferCLI: Environment.supportsCLI,
945
+ ...enhancementOptions
946
+ });
947
+ }
948
+
949
+ /**
950
+ * Memory types supported by the service
951
+ */
952
+ const MEMORY_TYPES = ['context', 'project', 'knowledge', 'reference', 'personal', 'workflow'];
953
+ /**
954
+ * Memory status values
955
+ */
956
+ const MEMORY_STATUSES = ['active', 'archived', 'draft', 'deleted'];
957
+ /**
958
+ * Validation schemas using Zod
959
+ */
960
+ const createMemorySchema = zod.z.object({
961
+ title: zod.z.string().min(1).max(500),
962
+ content: zod.z.string().min(1).max(50000),
963
+ summary: zod.z.string().max(1000).optional(),
964
+ memory_type: zod.z.enum(MEMORY_TYPES).default('context'),
965
+ topic_id: zod.z.string().uuid().optional(),
966
+ project_ref: zod.z.string().max(100).optional(),
967
+ tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).default([]),
968
+ metadata: zod.z.record(zod.z.unknown()).optional()
969
+ });
970
+ const updateMemorySchema = zod.z.object({
971
+ title: zod.z.string().min(1).max(500).optional(),
972
+ content: zod.z.string().min(1).max(50000).optional(),
973
+ summary: zod.z.string().max(1000).optional(),
974
+ memory_type: zod.z.enum(MEMORY_TYPES).optional(),
975
+ status: zod.z.enum(MEMORY_STATUSES).optional(),
976
+ topic_id: zod.z.string().uuid().nullable().optional(),
977
+ project_ref: zod.z.string().max(100).nullable().optional(),
978
+ tags: zod.z.array(zod.z.string().min(1).max(50)).max(20).optional(),
979
+ metadata: zod.z.record(zod.z.unknown()).optional()
980
+ });
981
+ const searchMemorySchema = zod.z.object({
982
+ query: zod.z.string().min(1).max(1000),
983
+ memory_types: zod.z.array(zod.z.enum(MEMORY_TYPES)).optional(),
984
+ tags: zod.z.array(zod.z.string()).optional(),
985
+ topic_id: zod.z.string().uuid().optional(),
986
+ project_ref: zod.z.string().optional(),
987
+ status: zod.z.enum(MEMORY_STATUSES).default('active'),
988
+ limit: zod.z.number().int().min(1).max(100).default(20),
989
+ threshold: zod.z.number().min(0).max(1).default(0.7)
990
+ });
991
+ const createTopicSchema = zod.z.object({
992
+ name: zod.z.string().min(1).max(100),
993
+ description: zod.z.string().max(500).optional(),
994
+ color: zod.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
995
+ icon: zod.z.string().max(50).optional(),
996
+ parent_topic_id: zod.z.string().uuid().optional()
997
+ });
998
+
999
+ /**
1000
+ * @lanonasis/memory-client
1001
+ *
1002
+ * Memory as a Service (MaaS) Client SDK for Lanonasis
1003
+ * Intelligent memory management with semantic search capabilities
1004
+ */
1005
+ // Main client
1006
+ // Constants
1007
+ const VERSION = '1.0.0';
1008
+ const CLIENT_NAME = '@lanonasis/memory-client';
1009
+ // Environment detection
1010
+ const isBrowser = typeof window !== 'undefined';
1011
+ const isNode = typeof globalThis !== 'undefined' && 'process' in globalThis && globalThis.process?.versions?.node;
1012
+ // Default configurations for different environments
1013
+ const defaultConfigs = {
1014
+ development: {
1015
+ apiUrl: 'http://localhost:3001',
1016
+ timeout: 30000,
1017
+ useGateway: false
1018
+ },
1019
+ production: {
1020
+ apiUrl: 'https://api.lanonasis.com',
1021
+ timeout: 15000,
1022
+ useGateway: true
1023
+ },
1024
+ gateway: {
1025
+ apiUrl: 'https://api.lanonasis.com',
1026
+ timeout: 10000,
1027
+ useGateway: true
1028
+ }
1029
+ };
1030
+ // Utility functions will be added in a future version to avoid circular imports
1031
+
1032
+ exports.CLIENT_NAME = CLIENT_NAME;
1033
+ exports.CLIIntegration = CLIIntegration;
1034
+ exports.ConfigPresets = ConfigPresets;
1035
+ exports.EnhancedMemoryClient = EnhancedMemoryClient;
1036
+ exports.Environment = Environment;
1037
+ exports.MEMORY_STATUSES = MEMORY_STATUSES;
1038
+ exports.MEMORY_TYPES = MEMORY_TYPES;
1039
+ exports.MemoryClient = MemoryClient;
1040
+ exports.VERSION = VERSION;
1041
+ exports.createEnhancedMemoryClient = createEnhancedMemoryClient;
1042
+ exports.createMemoryClient = createMemoryClient;
1043
+ exports.createMemorySchema = createMemorySchema;
1044
+ exports.createSmartConfig = createSmartConfig;
1045
+ exports.createTopicSchema = createTopicSchema;
1046
+ exports.defaultConfigs = defaultConfigs;
1047
+ exports.isBrowser = isBrowser;
1048
+ exports.isNode = isNode;
1049
+ exports.migrateToEnhanced = migrateToEnhanced;
1050
+ exports.searchMemorySchema = searchMemorySchema;
1051
+ exports.updateMemorySchema = updateMemorySchema;
1052
+ //# sourceMappingURL=index.js.map