@lanonasis/cli 3.3.15 → 3.4.15

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.
Files changed (36) hide show
  1. package/README.md +57 -13
  2. package/dist/commands/auth.js +7 -7
  3. package/dist/commands/completion.js +2 -0
  4. package/dist/commands/config.js +4 -4
  5. package/dist/commands/enhanced-memory.js +1 -1
  6. package/dist/commands/mcp.js +15 -9
  7. package/dist/core/achievements.js +1 -1
  8. package/dist/core/power-mode.js +5 -3
  9. package/dist/core/welcome.js +7 -6
  10. package/dist/enhanced-cli.js +6 -3
  11. package/dist/index-simple.js +5 -1
  12. package/dist/index.js +5 -1
  13. package/dist/mcp/access-control.d.ts +1 -1
  14. package/dist/mcp/access-control.js +4 -4
  15. package/dist/mcp/client/enhanced-client.js +4 -5
  16. package/dist/mcp/schemas/tool-schemas.d.ts +1 -1
  17. package/dist/mcp/schemas/tool-schemas.js +1 -1
  18. package/dist/mcp/server/lanonasis-server.d.ts +2 -1
  19. package/dist/mcp/server/lanonasis-server.js +7 -5
  20. package/dist/mcp/transports/transport-manager.js +3 -3
  21. package/dist/mcp-server.js +3 -3
  22. package/dist/utils/config.js +34 -6
  23. package/dist/utils/mcp-client.d.ts +4 -2
  24. package/dist/utils/mcp-client.js +86 -42
  25. package/package.json +3 -3
  26. package/dist/__tests__/auth-persistence.test.d.ts +0 -1
  27. package/dist/__tests__/auth-persistence.test.js +0 -243
  28. package/dist/__tests__/cross-device-integration.test.d.ts +0 -1
  29. package/dist/__tests__/cross-device-integration.test.js +0 -305
  30. package/dist/__tests__/mcp-connection-reliability.test.d.ts +0 -1
  31. package/dist/__tests__/mcp-connection-reliability.test.js +0 -489
  32. package/dist/__tests__/setup.d.ts +0 -1
  33. package/dist/__tests__/setup.js +0 -26
  34. package/dist/mcp/server/mcp/server/lanonasis-server.js +0 -911
  35. package/dist/mcp/server/utils/api.js +0 -431
  36. package/dist/mcp/server/utils/config.js +0 -855
@@ -65,7 +65,11 @@ program
65
65
  }
66
66
  process.env.CLI_OUTPUT_FORMAT = opts.output;
67
67
  // Auto-initialize MCP unless disabled
68
- if (opts.mcp !== false && !['init', 'auth', 'login', 'mcp', 'health', 'status'].includes(actionCommand.name())) {
68
+ const isMcpFlow = actionCommand.name() === 'mcp' ||
69
+ actionCommand.parent?.name?.() === 'mcp' ||
70
+ actionCommand.name() === 'mcp-server' ||
71
+ actionCommand.parent?.name?.() === 'mcp-server';
72
+ if (opts.mcp !== false && !isMcpFlow && !['init', 'auth', 'login', 'health', 'status'].includes(actionCommand.name())) {
69
73
  try {
70
74
  const client = getMCPClient();
71
75
  if (!client.isConnectedToServer()) {
package/dist/index.js CHANGED
@@ -52,7 +52,11 @@ program
52
52
  }
53
53
  process.env.CLI_OUTPUT_FORMAT = opts.output;
54
54
  // Auto-initialize MCP unless disabled
55
- if (opts.mcp !== false && !['init', 'auth', 'login', 'mcp', 'health', 'status'].includes(actionCommand.name())) {
55
+ const isMcpFlow = actionCommand.name() === 'mcp' ||
56
+ actionCommand.parent?.name?.() === 'mcp' ||
57
+ actionCommand.name() === 'mcp-server' ||
58
+ actionCommand.parent?.name?.() === 'mcp-server';
59
+ if (opts.mcp !== false && !isMcpFlow && !['init', 'auth', 'login', 'health', 'status'].includes(actionCommand.name())) {
56
60
  try {
57
61
  const client = getMCPClient();
58
62
  if (!client.isConnectedToServer()) {
@@ -50,7 +50,7 @@ export declare class MemoryAccessControl {
50
50
  /**
51
51
  * Revoke access to a memory or app
52
52
  */
53
- revokeAccess(userId: string, appId: string, memoryId?: string): Promise<void>;
53
+ revokeAccess(_userId: string, _appId: string, memoryId?: string): Promise<void>;
54
54
  /**
55
55
  * Get access logs for audit purposes
56
56
  */
@@ -123,8 +123,8 @@ export class MemoryAccessControl {
123
123
  /**
124
124
  * Revoke access to a memory or app
125
125
  */
126
- async revokeAccess(userId, appId, memoryId) {
127
- const key = `${userId}:${appId}`;
126
+ async revokeAccess(_userId, _appId, memoryId) {
127
+ const key = `${_userId}:${_appId}`;
128
128
  const existingRules = this.accessRules.get(key) || [];
129
129
  const updatedRules = existingRules.map(rule => {
130
130
  if (!memoryId || rule.memory_id === memoryId) {
@@ -133,7 +133,7 @@ export class MemoryAccessControl {
133
133
  return rule;
134
134
  });
135
135
  this.accessRules.set(key, updatedRules);
136
- logger.info('Access revoked', { userId, appId, memoryId });
136
+ logger.info('Access revoked', { userId: _userId, appId: _appId, memoryId });
137
137
  }
138
138
  /**
139
139
  * Get access logs for audit purposes
@@ -215,7 +215,7 @@ export class MemoryAccessControl {
215
215
  return [];
216
216
  }
217
217
  }
218
- async getSharedMemories(userId, appId) {
218
+ async getSharedMemories(_userId, _appId) {
219
219
  // This would implement logic to find memories shared with the user
220
220
  // through explicit permissions or app-level sharing
221
221
  return [];
@@ -115,7 +115,6 @@ export class EnhancedMCPClient extends EventEmitter {
115
115
  // HTTP transport is not directly supported by MCP SDK
116
116
  // Use stdio or websocket instead
117
117
  throw new Error('HTTP transport not directly supported. Use websocket or stdio transport.');
118
- break;
119
118
  case 'websocket':
120
119
  if (!config.url) {
121
120
  throw new Error('URL required for websocket transport');
@@ -225,7 +224,7 @@ export class EnhancedMCPClient extends EventEmitter {
225
224
  /**
226
225
  * Select the best server for a tool based on availability and latency
227
226
  */
228
- async selectBestServer(toolName) {
227
+ async selectBestServer(_toolName) {
229
228
  const availableServers = Array.from(this.clients.keys()).filter(name => {
230
229
  const status = this.connectionStatus.get(name);
231
230
  return status?.status === 'connected';
@@ -240,7 +239,7 @@ export class EnhancedMCPClient extends EventEmitter {
240
239
  /**
241
240
  * Select a failover server
242
241
  */
243
- async selectFailoverServer(excludeServer, toolName) {
242
+ async selectFailoverServer(excludeServer, _toolName) {
244
243
  const availableServers = Array.from(this.clients.keys()).filter(name => {
245
244
  const status = this.connectionStatus.get(name);
246
245
  return name !== excludeServer && status?.status === 'connected';
@@ -318,7 +317,7 @@ export class EnhancedMCPClient extends EventEmitter {
318
317
  /**
319
318
  * Get server configuration (placeholder - should be stored during connect)
320
319
  */
321
- getServerConfig(serverName) {
320
+ getServerConfig(_serverName) {
322
321
  // TODO: Store and retrieve server configs
323
322
  return null;
324
323
  }
@@ -343,7 +342,7 @@ export class EnhancedMCPClient extends EventEmitter {
343
342
  await client.close();
344
343
  console.log(chalk.gray(`Disconnected from ${name}`));
345
344
  }
346
- catch (error) {
345
+ catch {
347
346
  console.log(chalk.yellow(`Warning: Error disconnecting from ${name}`));
348
347
  }
349
348
  }
@@ -371,7 +371,7 @@ export declare class SchemaValidator {
371
371
  /**
372
372
  * Get schema as JSON Schema for documentation
373
373
  */
374
- static toJsonSchema(schema: z.ZodSchema<any>): any;
374
+ static toJsonSchema(_schema: z.ZodSchema<any>): any;
375
375
  }
376
376
  export declare const MCPSchemas: {
377
377
  memory: {
@@ -333,7 +333,7 @@ export class SchemaValidator {
333
333
  /**
334
334
  * Get schema as JSON Schema for documentation
335
335
  */
336
- static toJsonSchema(schema) {
336
+ static toJsonSchema(_schema) {
337
337
  // This would require zodToJsonSchema package
338
338
  // For now, return a simplified version
339
339
  return {
@@ -59,7 +59,8 @@ export declare class LanonasisMCPServer {
59
59
  */
60
60
  private registerPrompts; /**
61
61
 
62
- * Handle tool calls
62
+ /**
63
+ * Handle tool calls
63
64
  */
64
65
  private handleToolCall;
65
66
  /**
@@ -600,9 +600,10 @@ Please choose an option (1-4):`
600
600
  });
601
601
  } /**
602
602
 
603
- * Handle tool calls
603
+ /**
604
+ * Handle tool calls
604
605
  */
605
- async handleToolCall(name, args, clientId) {
606
+ async handleToolCall(name, args, _clientId) {
606
607
  // Ensure we're initialized
607
608
  if (!this.apiClient) {
608
609
  await this.initialize();
@@ -666,7 +667,7 @@ Please choose an option (1-4):`
666
667
  // Transport management operations
667
668
  case 'transport_status':
668
669
  return this.getTransportStatus();
669
- case 'transport_test':
670
+ case 'transport_test': {
670
671
  if (!args.transport) {
671
672
  throw new Error('transport is required');
672
673
  }
@@ -676,6 +677,7 @@ Please choose an option (1-4):`
676
677
  available: isAvailable,
677
678
  tested_at: new Date().toISOString()
678
679
  };
680
+ }
679
681
  case 'transport_reset_failures':
680
682
  if (args.transport) {
681
683
  this.transportFailures.delete(args.transport);
@@ -1178,7 +1180,7 @@ Please choose an option (1-4):`
1178
1180
  }
1179
1181
  return true;
1180
1182
  }
1181
- catch (error) {
1183
+ catch {
1182
1184
  return false;
1183
1185
  }
1184
1186
  }
@@ -1199,7 +1201,7 @@ Please choose an option (1-4):`
1199
1201
  }
1200
1202
  return true;
1201
1203
  }
1202
- catch (error) {
1204
+ catch {
1203
1205
  return false;
1204
1206
  }
1205
1207
  }
@@ -162,7 +162,7 @@ class WebSocketTransport extends EventEmitter {
162
162
  const message = JSON.parse(data.toString());
163
163
  this.emit('message', message);
164
164
  }
165
- catch (error) {
165
+ catch {
166
166
  this.emit('error', new Error('Failed to parse WebSocket message'));
167
167
  }
168
168
  });
@@ -270,7 +270,7 @@ class SSETransport extends EventEmitter {
270
270
  const data = JSON.parse(event.data);
271
271
  this.emit('message', data);
272
272
  }
273
- catch (error) {
273
+ catch {
274
274
  this.emit('error', new Error('Failed to parse SSE message'));
275
275
  }
276
276
  };
@@ -282,7 +282,7 @@ class SSETransport extends EventEmitter {
282
282
  };
283
283
  });
284
284
  }
285
- async send(data) {
285
+ async send(_data) {
286
286
  // SSE is receive-only, but we can send data via HTTP POST
287
287
  throw new Error('SSE transport is read-only. Use HTTP for sending data.');
288
288
  }
@@ -20,7 +20,7 @@ export class CLIMCPServer {
20
20
  */
21
21
  async start(options = {}) {
22
22
  await this.config.init();
23
- const { mode = 'stdio', port = 3001, verbose = false, useRemote = this.config.shouldUseRemoteMCP() } = options;
23
+ const { useRemote = this.config.shouldUseRemoteMCP() } = options;
24
24
  if (useRemote) {
25
25
  await this.startRemoteMCP(options);
26
26
  }
@@ -33,8 +33,8 @@ export class CLIMCPServer {
33
33
  */
34
34
  async startLocalMCP(options) {
35
35
  const { mode, port, verbose } = options;
36
- // Path to CLI-aligned MCP server in submodule
37
- const mcpServerPath = join(__dirname, '../../../mcp-server/dist/cli-aligned-mcp-server.js');
36
+ // Path to production MCP server (uses CommonJS, no build needed)
37
+ const mcpServerPath = join(__dirname, '../../../mcp-server/src/production-mcp-server.cjs');
38
38
  const args = mode === 'http' ? ['--http'] : ['--stdio'];
39
39
  if (verbose) {
40
40
  console.error('🚀 Starting CLI-aligned MCP Server...');
@@ -446,6 +446,8 @@ export class CLIConfig {
446
446
  catch {
447
447
  // Invalid token, don't store user info or expiry
448
448
  this.config.tokenExpiry = undefined;
449
+ // Mark as non-JWT (e.g., OAuth/CLI token)
450
+ this.config.authMethod = this.config.authMethod || 'oauth';
449
451
  }
450
452
  await this.save();
451
453
  }
@@ -493,8 +495,32 @@ export class CLIConfig {
493
495
  locallyValid = false;
494
496
  }
495
497
  }
496
- // If expired locally, no need to check server
498
+ // If not locally valid, attempt server verification before failing
497
499
  if (!locallyValid) {
500
+ try {
501
+ const axios = (await import('axios')).default;
502
+ const endpoints = [
503
+ 'http://localhost:4000/v1/auth/verify-token',
504
+ 'https://auth.lanonasis.com/v1/auth/verify-token',
505
+ 'https://api.lanonasis.com/auth/verify'
506
+ ];
507
+ for (const endpoint of endpoints) {
508
+ try {
509
+ const resp = await axios.post(endpoint, { token }, { timeout: 3000 });
510
+ if (resp.data?.valid === true) {
511
+ this.authCheckCache = { isValid: true, timestamp: Date.now() };
512
+ return true;
513
+ }
514
+ }
515
+ catch {
516
+ // try next endpoint
517
+ continue;
518
+ }
519
+ }
520
+ }
521
+ catch {
522
+ // ignore, will fall back to failure below
523
+ }
498
524
  this.authCheckCache = { isValid: false, timestamp: Date.now() };
499
525
  return false;
500
526
  }
@@ -515,7 +541,7 @@ export class CLIConfig {
515
541
  break;
516
542
  }
517
543
  }
518
- catch (err) {
544
+ catch {
519
545
  // Try next endpoint
520
546
  continue;
521
547
  }
@@ -527,7 +553,7 @@ export class CLIConfig {
527
553
  this.authCheckCache = { isValid: true, timestamp: Date.now() };
528
554
  return true;
529
555
  }
530
- catch (error) {
556
+ catch {
531
557
  // If all server checks fail, fall back to local validation
532
558
  // This allows offline usage but is less secure
533
559
  console.warn('⚠️ Unable to verify token with server, using local validation');
@@ -591,7 +617,7 @@ export class CLIConfig {
591
617
  await this.save();
592
618
  return true;
593
619
  }
594
- catch (error) {
620
+ catch {
595
621
  // Increment failure count
596
622
  await this.incrementFailureCount();
597
623
  return false;
@@ -630,7 +656,7 @@ export class CLIConfig {
630
656
  }
631
657
  }
632
658
  }
633
- catch (error) {
659
+ catch {
634
660
  // If refresh fails, mark credentials as potentially invalid
635
661
  await this.incrementFailureCount();
636
662
  }
@@ -697,7 +723,9 @@ export class CLIConfig {
697
723
  }
698
724
  // MCP-specific helpers
699
725
  getMCPServerPath() {
700
- return this.config.mcpServerPath || path.join(process.cwd(), 'onasis-gateway/mcp-server/server.js');
726
+ // Only return an explicitly configured path. No implicit bundled defaults.
727
+ // Returning an empty string if unset helps callers decide how to proceed safely.
728
+ return this.config.mcpServerPath || '';
701
729
  }
702
730
  getMCPServerUrl() {
703
731
  return this.config.discoveredServices?.mcp_ws_base ||
@@ -4,6 +4,7 @@ interface MCPConnectionOptions {
4
4
  useRemote?: boolean;
5
5
  useWebSocket?: boolean;
6
6
  connectionMode?: 'local' | 'remote' | 'websocket';
7
+ localArgs?: string[];
7
8
  }
8
9
  /**
9
10
  * Interface for MCP tool arguments
@@ -24,10 +25,10 @@ export interface MCPToolResponse {
24
25
  title?: string;
25
26
  memory_type?: string;
26
27
  length?: number;
27
- forEach?: (callback: (item: any, index: number) => void) => void;
28
+ forEach?: (callback: (item: unknown, index: number) => void) => void;
28
29
  code?: number;
29
30
  message?: string;
30
- response?: any;
31
+ response?: unknown;
31
32
  }
32
33
  /**
33
34
  * Interface for MCP WebSocket messages
@@ -54,6 +55,7 @@ export declare class MCPClient {
54
55
  private healthCheckInterval;
55
56
  private connectionStartTime;
56
57
  private lastHealthCheck;
58
+ private activeConnectionMode;
57
59
  constructor();
58
60
  /**
59
61
  * Initialize the MCP client configuration