@lanonasis/cli 3.6.5 → 3.7.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.
Files changed (43) hide show
  1. package/README.md +19 -2
  2. package/dist/commands/api-keys.d.ts +2 -1
  3. package/dist/commands/api-keys.js +73 -78
  4. package/dist/commands/auth.js +244 -177
  5. package/dist/commands/completion.js +31 -39
  6. package/dist/commands/config.js +162 -201
  7. package/dist/commands/enhanced-memory.js +11 -17
  8. package/dist/commands/guide.js +79 -88
  9. package/dist/commands/init.js +14 -20
  10. package/dist/commands/mcp.d.ts +10 -0
  11. package/dist/commands/mcp.js +215 -156
  12. package/dist/commands/memory.js +77 -83
  13. package/dist/commands/organization.js +15 -21
  14. package/dist/commands/topics.js +52 -58
  15. package/dist/core/achievements.js +19 -26
  16. package/dist/core/architecture.js +42 -59
  17. package/dist/core/dashboard.js +71 -81
  18. package/dist/core/error-handler.js +30 -39
  19. package/dist/core/power-mode.js +46 -53
  20. package/dist/core/progress.js +35 -44
  21. package/dist/core/welcome.js +56 -64
  22. package/dist/enhanced-cli.js +49 -58
  23. package/dist/index-simple.js +75 -113
  24. package/dist/index.js +64 -69
  25. package/dist/mcp/access-control.js +13 -17
  26. package/dist/mcp/client/enhanced-client.js +17 -28
  27. package/dist/mcp/enhanced-server.js +10 -14
  28. package/dist/mcp/logger.js +3 -7
  29. package/dist/mcp/memory-state.js +13 -17
  30. package/dist/mcp/schemas/tool-schemas.d.ts +16 -16
  31. package/dist/mcp/schemas/tool-schemas.js +122 -126
  32. package/dist/mcp/server/lanonasis-server.js +66 -57
  33. package/dist/mcp/transports/transport-manager.js +18 -25
  34. package/dist/mcp/vector-store.js +6 -10
  35. package/dist/mcp-server.js +23 -27
  36. package/dist/utils/api.js +21 -27
  37. package/dist/utils/config.d.ts +2 -1
  38. package/dist/utils/config.js +65 -78
  39. package/dist/utils/formatting.js +6 -14
  40. package/dist/utils/hash-utils.d.ts +23 -0
  41. package/dist/utils/hash-utils.js +37 -0
  42. package/dist/utils/mcp-client.js +76 -117
  43. package/package.json +36 -5
@@ -1,29 +1,23 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.diagnoseCommand = diagnoseCommand;
7
- exports.loginCommand = loginCommand;
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const inquirer_1 = __importDefault(require("inquirer"));
10
- const ora_1 = __importDefault(require("ora"));
11
- const open_1 = __importDefault(require("open"));
12
- const crypto_1 = __importDefault(require("crypto"));
13
- const http_1 = __importDefault(require("http"));
14
- const url_1 = __importDefault(require("url"));
15
- const api_js_1 = require("../utils/api.js");
16
- const config_js_1 = require("../utils/config.js");
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import open from 'open';
5
+ import crypto from 'crypto';
6
+ import http from 'http';
7
+ import url from 'url';
8
+ import axios from 'axios';
9
+ import { apiClient } from '../utils/api.js';
10
+ import { CLIConfig } from '../utils/config.js';
17
11
  // Color scheme
18
12
  const colors = {
19
- primary: chalk_1.default.blue.bold,
20
- success: chalk_1.default.green,
21
- warning: chalk_1.default.yellow,
22
- error: chalk_1.default.red,
23
- info: chalk_1.default.cyan,
24
- accent: chalk_1.default.magenta,
25
- muted: chalk_1.default.gray,
26
- highlight: chalk_1.default.white.bold
13
+ primary: chalk.blue.bold,
14
+ success: chalk.green,
15
+ warning: chalk.yellow,
16
+ error: chalk.red,
17
+ info: chalk.cyan,
18
+ accent: chalk.magenta,
19
+ muted: chalk.gray,
20
+ highlight: chalk.white.bold
27
21
  };
28
22
  // Helper function to handle authentication delays
29
23
  async function handleAuthDelay(config) {
@@ -32,15 +26,15 @@ async function handleAuthDelay(config) {
32
26
  const failureCount = config.getFailureCount();
33
27
  const lastFailure = config.getLastAuthFailure();
34
28
  console.log();
35
- console.log(chalk_1.default.yellow(`⚠️ Multiple authentication failures detected (${failureCount} attempts)`));
29
+ console.log(chalk.yellow(`⚠️ Multiple authentication failures detected (${failureCount} attempts)`));
36
30
  if (lastFailure) {
37
31
  const lastFailureDate = new Date(lastFailure);
38
- console.log(chalk_1.default.gray(`Last failure: ${lastFailureDate.toLocaleString()}`));
32
+ console.log(chalk.gray(`Last failure: ${lastFailureDate.toLocaleString()}`));
39
33
  }
40
- console.log(chalk_1.default.yellow(`Waiting ${Math.round(delayMs / 1000)} seconds before retry...`));
41
- console.log(chalk_1.default.gray('This delay helps prevent account lockouts and reduces server load.'));
34
+ console.log(chalk.yellow(`Waiting ${Math.round(delayMs / 1000)} seconds before retry...`));
35
+ console.log(chalk.gray('This delay helps prevent account lockouts and reduces server load.'));
42
36
  // Show countdown
43
- const spinner = (0, ora_1.default)(`Waiting ${Math.round(delayMs / 1000)} seconds...`).start();
37
+ const spinner = ora(`Waiting ${Math.round(delayMs / 1000)} seconds...`).start();
44
38
  await new Promise(resolve => setTimeout(resolve, delayMs));
45
39
  spinner.succeed('Ready to retry authentication');
46
40
  console.log();
@@ -54,70 +48,70 @@ async function handleAuthenticationFailure(error, config, authMethod = 'jwt') {
54
48
  // Determine error type and provide specific guidance
55
49
  const errorType = categorizeAuthError(error);
56
50
  console.log();
57
- console.log(chalk_1.default.red('✖ Authentication failed'));
51
+ console.log(chalk.red('✖ Authentication failed'));
58
52
  switch (errorType) {
59
53
  case 'invalid_credentials':
60
- console.log(chalk_1.default.red('Invalid credentials provided'));
54
+ console.log(chalk.red('Invalid credentials provided'));
61
55
  if (authMethod === 'vendor_key') {
62
- console.log(chalk_1.default.gray('• Verify the vendor key matches the value shown in your dashboard'));
63
- console.log(chalk_1.default.gray('• Confirm the key is active and has not been revoked'));
64
- console.log(chalk_1.default.gray('• Ensure you copied the entire key without extra spaces'));
56
+ console.log(chalk.gray('• Verify the vendor key matches the value shown in your dashboard'));
57
+ console.log(chalk.gray('• Confirm the key is active and has not been revoked'));
58
+ console.log(chalk.gray('• Ensure you copied the entire key without extra spaces'));
65
59
  }
66
60
  else {
67
- console.log(chalk_1.default.gray('• Double-check your email and password'));
68
- console.log(chalk_1.default.gray('• Passwords are case-sensitive'));
69
- console.log(chalk_1.default.gray('• Consider resetting your password if needed'));
61
+ console.log(chalk.gray('• Double-check your email and password'));
62
+ console.log(chalk.gray('• Passwords are case-sensitive'));
63
+ console.log(chalk.gray('• Consider resetting your password if needed'));
70
64
  }
71
65
  break;
72
66
  case 'network_error':
73
- console.log(chalk_1.default.red('Network connection failed'));
74
- console.log(chalk_1.default.gray('• Check your internet connection'));
75
- console.log(chalk_1.default.gray('• Verify you can access https://auth.lanonasis.com'));
76
- console.log(chalk_1.default.gray('• Try again in a few moments'));
67
+ console.log(chalk.red('Network connection failed'));
68
+ console.log(chalk.gray('• Check your internet connection'));
69
+ console.log(chalk.gray('• Verify you can access https://auth.lanonasis.com'));
70
+ console.log(chalk.gray('• Try again in a few moments'));
77
71
  if (failureCount >= 2) {
78
- console.log(chalk_1.default.gray('• Consider using a different network if issues persist'));
72
+ console.log(chalk.gray('• Consider using a different network if issues persist'));
79
73
  }
80
74
  break;
81
75
  case 'server_error':
82
- console.log(chalk_1.default.red('Server temporarily unavailable'));
83
- console.log(chalk_1.default.gray('• The authentication service may be experiencing issues'));
84
- console.log(chalk_1.default.gray('• Please try again in a few minutes'));
85
- console.log(chalk_1.default.gray('• Check https://status.lanonasis.com for service status'));
76
+ console.log(chalk.red('Server temporarily unavailable'));
77
+ console.log(chalk.gray('• The authentication service may be experiencing issues'));
78
+ console.log(chalk.gray('• Please try again in a few minutes'));
79
+ console.log(chalk.gray('• Check https://status.lanonasis.com for service status'));
86
80
  break;
87
81
  case 'rate_limited':
88
- console.log(chalk_1.default.red('Too many authentication attempts'));
89
- console.log(chalk_1.default.gray('• Please wait before trying again'));
90
- console.log(chalk_1.default.gray('• Rate limiting helps protect your account'));
91
- console.log(chalk_1.default.gray('• Consider using a vendor key for automated access'));
82
+ console.log(chalk.red('Too many authentication attempts'));
83
+ console.log(chalk.gray('• Please wait before trying again'));
84
+ console.log(chalk.gray('• Rate limiting helps protect your account'));
85
+ console.log(chalk.gray('• Consider using a vendor key for automated access'));
92
86
  break;
93
87
  case 'expired_token':
94
- console.log(chalk_1.default.red('Authentication token has expired'));
95
- console.log(chalk_1.default.gray('• Please log in again to refresh your session'));
96
- console.log(chalk_1.default.gray('• Consider using a vendor key for longer-term access'));
88
+ console.log(chalk.red('Authentication token has expired'));
89
+ console.log(chalk.gray('• Please log in again to refresh your session'));
90
+ console.log(chalk.gray('• Consider using a vendor key for longer-term access'));
97
91
  await config.clearInvalidCredentials();
98
92
  break;
99
93
  default:
100
- console.log(chalk_1.default.red(`Unexpected error: ${error.message || 'Unknown error'}`));
101
- console.log(chalk_1.default.gray('• Please try again'));
102
- console.log(chalk_1.default.gray('• If the problem persists, contact support'));
94
+ console.log(chalk.red(`Unexpected error: ${error.message || 'Unknown error'}`));
95
+ console.log(chalk.gray('• Please try again'));
96
+ console.log(chalk.gray('• If the problem persists, contact support'));
103
97
  }
104
98
  // Progressive guidance for repeated failures
105
99
  if (failureCount >= 3) {
106
100
  console.log();
107
- console.log(chalk_1.default.yellow('💡 Multiple failures detected. Recovery options:'));
101
+ console.log(chalk.yellow('💡 Multiple failures detected. Recovery options:'));
108
102
  if (authMethod === 'vendor_key') {
109
- console.log(chalk_1.default.cyan('• Generate a new vendor key from your dashboard'));
110
- console.log(chalk_1.default.cyan('• Try: lanonasis auth logout && lanonasis auth login'));
111
- console.log(chalk_1.default.cyan('• Switch to browser login: lanonasis auth login (choose Browser Login)'));
103
+ console.log(chalk.cyan('• Generate a new vendor key from your dashboard'));
104
+ console.log(chalk.cyan('• Try: lanonasis auth logout && lanonasis auth login'));
105
+ console.log(chalk.cyan('• Switch to browser login: lanonasis auth login (choose Browser Login)'));
112
106
  }
113
107
  else {
114
- console.log(chalk_1.default.cyan('• Reset your password if you\'re unsure'));
115
- console.log(chalk_1.default.cyan('• Try vendor key authentication instead'));
116
- console.log(chalk_1.default.cyan('• Clear stored config: lanonasis auth logout'));
108
+ console.log(chalk.cyan('• Reset your password if you\'re unsure'));
109
+ console.log(chalk.cyan('• Try vendor key authentication instead'));
110
+ console.log(chalk.cyan('• Clear stored config: lanonasis auth logout'));
117
111
  }
118
112
  if (failureCount >= 5) {
119
- console.log(chalk_1.default.yellow('• Consider contacting support if issues persist'));
120
- console.log(chalk_1.default.gray('• Include error details and your email address'));
113
+ console.log(chalk.yellow('• Consider contacting support if issues persist'));
114
+ console.log(chalk.gray('• Include error details and your email address'));
121
115
  }
122
116
  }
123
117
  }
@@ -181,9 +175,9 @@ function categorizeAuthError(error) {
181
175
  */
182
176
  function generatePKCE() {
183
177
  // Generate random verifier (43-128 chars, base64url)
184
- const verifier = crypto_1.default.randomBytes(32).toString('base64url');
178
+ const verifier = crypto.randomBytes(32).toString('base64url');
185
179
  // Generate challenge: base64url(sha256(verifier))
186
- const challenge = crypto_1.default
180
+ const challenge = crypto
187
181
  .createHash('sha256')
188
182
  .update(verifier)
189
183
  .digest('base64url');
@@ -194,8 +188,8 @@ function generatePKCE() {
194
188
  */
195
189
  function createCallbackServer(port = 8888) {
196
190
  return new Promise((resolve, reject) => {
197
- const server = http_1.default.createServer((req, res) => {
198
- const parsedUrl = url_1.default.parse(req.url, true);
191
+ const server = http.createServer((req, res) => {
192
+ const parsedUrl = url.parse(req.url, true);
199
193
  if (parsedUrl.pathname === '/callback') {
200
194
  const { code, state, error, error_description } = parsedUrl.query;
201
195
  // Send response to browser
@@ -237,7 +231,7 @@ function createCallbackServer(port = 8888) {
237
231
  }
238
232
  });
239
233
  server.listen(port, () => {
240
- console.log(chalk_1.default.gray(` Local callback server listening on port ${port}`));
234
+ console.log(chalk.gray(` Local callback server listening on port ${port}`));
241
235
  });
242
236
  // Timeout after 5 minutes
243
237
  setTimeout(() => {
@@ -249,16 +243,40 @@ function createCallbackServer(port = 8888) {
249
243
  /**
250
244
  * Exchange authorization code for OAuth2 tokens
251
245
  */
252
- async function exchangeCodeForTokens(code, verifier, authBase) {
246
+ async function exchangeCodeForTokens(code, verifier, authBase, redirectUri) {
253
247
  const tokenEndpoint = `${authBase}/oauth/token`;
254
- const response = await api_js_1.apiClient.post(tokenEndpoint, {
255
- grant_type: 'authorization_code',
256
- code,
257
- code_verifier: verifier,
258
- client_id: 'lanonasis-cli',
259
- redirect_uri: 'http://localhost:8888/callback'
260
- });
261
- return response;
248
+ try {
249
+ // Use axios directly to have full control over error handling
250
+ const response = await axios.post(tokenEndpoint, {
251
+ grant_type: 'authorization_code',
252
+ code,
253
+ code_verifier: verifier,
254
+ client_id: 'lanonasis-cli',
255
+ redirect_uri: redirectUri
256
+ }, {
257
+ headers: {
258
+ 'Content-Type': 'application/json',
259
+ }
260
+ });
261
+ return response.data;
262
+ }
263
+ catch (error) {
264
+ // Extract detailed error information from axios error response
265
+ if (error.response) {
266
+ const errorData = error.response.data || {};
267
+ const status = error.response.status;
268
+ const errorMessage = errorData.error_description || errorData.error || error.message || `Request failed with status code ${status}`;
269
+ const details = errorData.details;
270
+ const enhancedError = new Error(errorMessage);
271
+ enhancedError.response = error.response;
272
+ enhancedError.status = status;
273
+ enhancedError.details = details;
274
+ enhancedError.errorData = errorData;
275
+ throw enhancedError;
276
+ }
277
+ // If it's not an axios error, just rethrow
278
+ throw error;
279
+ }
262
280
  }
263
281
  /**
264
282
  * Refresh OAuth2 access token using refresh token
@@ -270,7 +288,7 @@ async function refreshOAuth2Token(config) {
270
288
  }
271
289
  try {
272
290
  const authBase = config.getDiscoveredApiUrl();
273
- const response = await api_js_1.apiClient.post(`${authBase}/oauth/token`, {
291
+ const response = await apiClient.post(`${authBase}/oauth/token`, {
274
292
  grant_type: 'refresh_token',
275
293
  refresh_token: refreshToken,
276
294
  client_id: 'lanonasis-cli'
@@ -283,14 +301,14 @@ async function refreshOAuth2Token(config) {
283
301
  return true;
284
302
  }
285
303
  catch (error) {
286
- console.error(chalk_1.default.yellow('⚠️ Token refresh failed, please re-authenticate'));
304
+ console.error(chalk.yellow('⚠️ Token refresh failed, please re-authenticate'));
287
305
  return false;
288
306
  }
289
307
  }
290
- async function diagnoseCommand() {
291
- const config = new config_js_1.CLIConfig();
308
+ export async function diagnoseCommand() {
309
+ const config = new CLIConfig();
292
310
  await config.init();
293
- console.log(chalk_1.default.blue.bold('🔍 Authentication Diagnostic'));
311
+ console.log(chalk.blue.bold('🔍 Authentication Diagnostic'));
294
312
  console.log(colors.info('━'.repeat(50)));
295
313
  console.log();
296
314
  const diagnostics = {
@@ -306,146 +324,146 @@ async function diagnoseCommand() {
306
324
  deviceId: null
307
325
  };
308
326
  // Step 1: Check if config exists
309
- console.log(chalk_1.default.cyan('1. Configuration File'));
327
+ console.log(chalk.cyan('1. Configuration File'));
310
328
  try {
311
329
  const configExists = await config.exists();
312
330
  diagnostics.configExists = configExists;
313
331
  if (configExists) {
314
- console.log(chalk_1.default.green(' ✓ Config file exists at'), config.getConfigPath());
332
+ console.log(chalk.green(' ✓ Config file exists at'), config.getConfigPath());
315
333
  }
316
334
  else {
317
- console.log(chalk_1.default.red(' ✖ Config file not found at'), config.getConfigPath());
318
- console.log(chalk_1.default.gray(' → Run: lanonasis auth login'));
335
+ console.log(chalk.red(' ✖ Config file not found at'), config.getConfigPath());
336
+ console.log(chalk.gray(' → Run: lanonasis auth login'));
319
337
  }
320
338
  }
321
339
  catch (error) {
322
- console.log(chalk_1.default.red(' ✖ Error checking config:'), error instanceof Error ? error.message : 'Unknown error');
340
+ console.log(chalk.red(' ✖ Error checking config:'), error instanceof Error ? error.message : 'Unknown error');
323
341
  }
324
342
  // Step 2: Check stored credentials
325
- console.log(chalk_1.default.cyan('\n2. Stored Credentials'));
343
+ console.log(chalk.cyan('\n2. Stored Credentials'));
326
344
  const token = config.getToken();
327
345
  const vendorKey = config.getVendorKey();
328
346
  const authMethod = config.get('authMethod');
329
347
  if (vendorKey) {
330
348
  diagnostics.hasCredentials = true;
331
349
  diagnostics.credentialType = 'vendor_key';
332
- console.log(chalk_1.default.green(' ✓ Vendor key found'));
350
+ console.log(chalk.green(' ✓ Vendor key found'));
333
351
  // Validate vendor key presence
334
352
  const formatValidation = config.validateVendorKeyFormat(vendorKey);
335
353
  if (formatValidation !== true) {
336
- console.log(chalk_1.default.red(` ✖ Vendor key issue: ${formatValidation}`));
354
+ console.log(chalk.red(` ✖ Vendor key issue: ${formatValidation}`));
337
355
  }
338
356
  }
339
357
  else if (token) {
340
358
  diagnostics.hasCredentials = true;
341
359
  diagnostics.credentialType = authMethod === 'oauth' ? 'oauth' : 'jwt';
342
- console.log(chalk_1.default.green(` ✓ ${diagnostics.credentialType.toUpperCase()} token found`));
360
+ console.log(chalk.green(` ✓ ${diagnostics.credentialType.toUpperCase()} token found`));
343
361
  // Check token expiry
344
362
  try {
345
363
  const isAuth = await config.isAuthenticated();
346
364
  if (!isAuth) {
347
365
  diagnostics.tokenExpired = true;
348
- console.log(chalk_1.default.red(' ✖ Token is expired'));
366
+ console.log(chalk.red(' ✖ Token is expired'));
349
367
  }
350
368
  else {
351
- console.log(chalk_1.default.green(' ✓ Token is not expired'));
369
+ console.log(chalk.green(' ✓ Token is not expired'));
352
370
  }
353
371
  }
354
372
  catch (error) {
355
- console.log(chalk_1.default.yellow(' ⚠ Could not validate token expiry'));
373
+ console.log(chalk.yellow(' ⚠ Could not validate token expiry'));
356
374
  if (process.env.CLI_VERBOSE === 'true' && error instanceof Error) {
357
- console.log(chalk_1.default.gray(` ${error.message}`));
375
+ console.log(chalk.gray(` ${error.message}`));
358
376
  }
359
377
  }
360
378
  }
361
379
  else {
362
- console.log(chalk_1.default.red(' ✖ No credentials found'));
363
- console.log(chalk_1.default.gray(' → Run: lanonasis auth login'));
380
+ console.log(chalk.red(' ✖ No credentials found'));
381
+ console.log(chalk.gray(' → Run: lanonasis auth login'));
364
382
  }
365
383
  // Step 3: Check authentication failures
366
- console.log(chalk_1.default.cyan('\n3. Authentication History'));
384
+ console.log(chalk.cyan('\n3. Authentication History'));
367
385
  diagnostics.authFailures = config.getFailureCount();
368
386
  diagnostics.lastFailure = config.getLastAuthFailure() ?? null;
369
387
  if (diagnostics.authFailures === 0) {
370
- console.log(chalk_1.default.green(' ✓ No recent authentication failures'));
388
+ console.log(chalk.green(' ✓ No recent authentication failures'));
371
389
  }
372
390
  else {
373
- console.log(chalk_1.default.yellow(` ⚠ ${diagnostics.authFailures} recent authentication failures`));
391
+ console.log(chalk.yellow(` ⚠ ${diagnostics.authFailures} recent authentication failures`));
374
392
  if (diagnostics.lastFailure) {
375
393
  const lastFailureDate = new Date(diagnostics.lastFailure);
376
- console.log(chalk_1.default.gray(` Last failure: ${lastFailureDate.toLocaleString()}`));
394
+ console.log(chalk.gray(` Last failure: ${lastFailureDate.toLocaleString()}`));
377
395
  }
378
396
  if (config.shouldDelayAuth()) {
379
397
  const delayMs = config.getAuthDelayMs();
380
- console.log(chalk_1.default.yellow(` ⚠ Authentication delay active: ${Math.round(delayMs / 1000)}s`));
398
+ console.log(chalk.yellow(` ⚠ Authentication delay active: ${Math.round(delayMs / 1000)}s`));
381
399
  }
382
400
  }
383
401
  // Step 4: Test credential validation against server
384
- console.log(chalk_1.default.cyan('\n4. Server Validation'));
402
+ console.log(chalk.cyan('\n4. Server Validation'));
385
403
  if (diagnostics.hasCredentials) {
386
- const spinner = (0, ora_1.default)('Testing credentials against server...').start();
404
+ const spinner = ora('Testing credentials against server...').start();
387
405
  try {
388
406
  const isValid = await config.validateStoredCredentials();
389
407
  diagnostics.credentialsValid = isValid;
390
408
  if (isValid) {
391
409
  spinner.succeed('Credentials are valid');
392
- console.log(chalk_1.default.green(' ✓ Server authentication successful'));
410
+ console.log(chalk.green(' ✓ Server authentication successful'));
393
411
  }
394
412
  else {
395
413
  spinner.fail('Credentials are invalid');
396
- console.log(chalk_1.default.red(' ✖ Server rejected credentials'));
397
- console.log(chalk_1.default.gray(' → Try: lanonasis auth login'));
414
+ console.log(chalk.red(' ✖ Server rejected credentials'));
415
+ console.log(chalk.gray(' → Try: lanonasis auth login'));
398
416
  }
399
417
  }
400
418
  catch (error) {
401
419
  spinner.fail('Server validation failed');
402
- console.log(chalk_1.default.red(' ✖ Could not validate with server:'));
403
- console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
420
+ console.log(chalk.red(' ✖ Could not validate with server:'));
421
+ console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
404
422
  }
405
423
  }
406
424
  else {
407
- console.log(chalk_1.default.gray(' - Skipped (no credentials to validate)'));
425
+ console.log(chalk.gray(' - Skipped (no credentials to validate)'));
408
426
  }
409
427
  // Step 5: Test endpoint connectivity
410
- console.log(chalk_1.default.cyan('\n5. Endpoint Connectivity'));
411
- const spinner2 = (0, ora_1.default)('Testing authentication endpoints...').start();
428
+ console.log(chalk.cyan('\n5. Endpoint Connectivity'));
429
+ const spinner2 = ora('Testing authentication endpoints...').start();
412
430
  try {
413
431
  await config.discoverServices();
414
432
  diagnostics.serviceDiscovery = true;
415
433
  const services = config.get('discoveredServices');
416
434
  if (services) {
417
435
  spinner2.succeed('Authentication endpoints reachable');
418
- console.log(chalk_1.default.green(' ✓ Service discovery successful'));
419
- console.log(chalk_1.default.gray(` Auth endpoint: ${services.auth_base}`));
436
+ console.log(chalk.green(' ✓ Service discovery successful'));
437
+ console.log(chalk.gray(` Auth endpoint: ${services.auth_base}`));
420
438
  diagnostics.endpointsReachable = true;
421
439
  }
422
440
  else {
423
441
  spinner2.warn('Using fallback endpoints');
424
- console.log(chalk_1.default.yellow(' ⚠ Service discovery failed, using fallbacks'));
442
+ console.log(chalk.yellow(' ⚠ Service discovery failed, using fallbacks'));
425
443
  diagnostics.endpointsReachable = true; // Fallbacks still work
426
444
  }
427
445
  }
428
446
  catch (error) {
429
447
  spinner2.fail('Endpoint connectivity failed');
430
- console.log(chalk_1.default.red(' ✖ Cannot reach authentication endpoints'));
431
- console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
432
- console.log(chalk_1.default.gray(' → Check internet connection'));
448
+ console.log(chalk.red(' ✖ Cannot reach authentication endpoints'));
449
+ console.log(chalk.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
450
+ console.log(chalk.gray(' → Check internet connection'));
433
451
  }
434
452
  // Step 6: Device identification
435
- console.log(chalk_1.default.cyan('\n6. Device Information'));
453
+ console.log(chalk.cyan('\n6. Device Information'));
436
454
  try {
437
455
  const deviceId = await config.getDeviceId();
438
456
  diagnostics.deviceId = deviceId;
439
- console.log(chalk_1.default.green(' ✓ Device ID:'), chalk_1.default.gray(deviceId));
457
+ console.log(chalk.green(' ✓ Device ID:'), chalk.gray(deviceId));
440
458
  }
441
459
  catch (error) {
442
- console.log(chalk_1.default.yellow(' ⚠ Could not get device ID'));
460
+ console.log(chalk.yellow(' ⚠ Could not get device ID'));
443
461
  if (process.env.CLI_VERBOSE === 'true' && error instanceof Error) {
444
- console.log(chalk_1.default.gray(` ${error.message}`));
462
+ console.log(chalk.gray(` ${error.message}`));
445
463
  }
446
464
  }
447
465
  // Summary and recommendations
448
- console.log(chalk_1.default.blue.bold('\n📋 Diagnostic Summary'));
466
+ console.log(chalk.blue.bold('\n📋 Diagnostic Summary'));
449
467
  console.log(colors.info('━'.repeat(50)));
450
468
  const issues = [];
451
469
  const recommendations = [];
@@ -474,32 +492,32 @@ async function diagnoseCommand() {
474
492
  recommendations.push('Check internet connection and firewall settings');
475
493
  }
476
494
  if (issues.length === 0) {
477
- console.log(chalk_1.default.green('✅ All authentication checks passed!'));
478
- console.log(chalk_1.default.cyan(' Your authentication is working correctly.'));
495
+ console.log(chalk.green('✅ All authentication checks passed!'));
496
+ console.log(chalk.cyan(' Your authentication is working correctly.'));
479
497
  }
480
498
  else {
481
- console.log(chalk_1.default.red(`❌ Found ${issues.length} issue(s):`));
499
+ console.log(chalk.red(`❌ Found ${issues.length} issue(s):`));
482
500
  issues.forEach(issue => {
483
- console.log(chalk_1.default.red(` • ${issue}`));
501
+ console.log(chalk.red(` • ${issue}`));
484
502
  });
485
- console.log(chalk_1.default.yellow('\n💡 Recommended actions:'));
503
+ console.log(chalk.yellow('\n💡 Recommended actions:'));
486
504
  recommendations.forEach(rec => {
487
- console.log(chalk_1.default.cyan(` • ${rec}`));
505
+ console.log(chalk.cyan(` • ${rec}`));
488
506
  });
489
507
  }
490
508
  // Additional troubleshooting info
491
509
  if (diagnostics.authFailures > 0 || !diagnostics.credentialsValid) {
492
- console.log(chalk_1.default.gray('\n🔧 Additional troubleshooting:'));
493
- console.log(chalk_1.default.gray(' • Verify the vendor key matches the value shown in your dashboard'));
494
- console.log(chalk_1.default.gray(' • Check if your key is active in the dashboard'));
495
- console.log(chalk_1.default.gray(' • Try browser authentication: lanonasis auth login (choose Browser Login)'));
496
- console.log(chalk_1.default.gray(' • Contact support if issues persist'));
510
+ console.log(chalk.gray('\n🔧 Additional troubleshooting:'));
511
+ console.log(chalk.gray(' • Verify the vendor key matches the value shown in your dashboard'));
512
+ console.log(chalk.gray(' • Check if your key is active in the dashboard'));
513
+ console.log(chalk.gray(' • Try browser authentication: lanonasis auth login (choose Browser Login)'));
514
+ console.log(chalk.gray(' • Contact support if issues persist'));
497
515
  }
498
516
  }
499
- async function loginCommand(options) {
500
- const config = new config_js_1.CLIConfig();
517
+ export async function loginCommand(options) {
518
+ const config = new CLIConfig();
501
519
  await config.init();
502
- console.log(chalk_1.default.blue.bold('🔐 Onasis-Core Golden Contract Authentication'));
520
+ console.log(chalk.blue.bold('🔐 Onasis-Core Golden Contract Authentication'));
503
521
  console.log(colors.info('━'.repeat(50)));
504
522
  console.log();
505
523
  // Debug: Check options
@@ -521,7 +539,7 @@ async function loginCommand(options) {
521
539
  return;
522
540
  }
523
541
  // Show authentication options
524
- const authChoice = await inquirer_1.default.prompt([
542
+ const authChoice = await inquirer.prompt([
525
543
  {
526
544
  type: 'list',
527
545
  name: 'method',
@@ -557,14 +575,14 @@ async function loginCommand(options) {
557
575
  async function handleVendorKeyAuth(vendorKey, config) {
558
576
  // Check for authentication delay before attempting
559
577
  await handleAuthDelay(config);
560
- const spinner = (0, ora_1.default)('Validating vendor key...').start();
578
+ const spinner = ora('Validating vendor key...').start();
561
579
  try {
562
580
  await config.setVendorKey(vendorKey);
563
581
  // Test the vendor key with a health check
564
- await api_js_1.apiClient.get('/health');
582
+ await apiClient.get('/health');
565
583
  spinner.succeed('Vendor key authentication successful');
566
584
  console.log();
567
- console.log(chalk_1.default.green('✓ Authenticated with vendor key'));
585
+ console.log(chalk.green('✓ Authenticated with vendor key'));
568
586
  console.log(colors.info('Ready to use Onasis-Core services'));
569
587
  }
570
588
  catch (error) {
@@ -576,16 +594,16 @@ async function handleVendorKeyAuth(vendorKey, config) {
576
594
  }
577
595
  async function handleVendorKeyFlow(config) {
578
596
  console.log();
579
- console.log(chalk_1.default.yellow('🔑 Vendor Key Authentication'));
580
- console.log(chalk_1.default.gray('Vendor keys provide secure API access for automation and integrations.'));
597
+ console.log(chalk.yellow('🔑 Vendor Key Authentication'));
598
+ console.log(chalk.gray('Vendor keys provide secure API access for automation and integrations.'));
581
599
  console.log();
582
600
  // Enhanced guidance for obtaining vendor keys
583
- console.log(chalk_1.default.cyan('📋 How to get your vendor key:'));
584
- console.log(chalk_1.default.gray('1. Visit your Lanonasis dashboard at https://dashboard.lanonasis.com'));
585
- console.log(chalk_1.default.gray('2. Navigate to Settings → API Keys'));
586
- console.log(chalk_1.default.gray('3. Click "Generate New Key" and copy the full key value'));
601
+ console.log(chalk.cyan('📋 How to get your vendor key:'));
602
+ console.log(chalk.gray('1. Visit your Lanonasis dashboard at https://dashboard.lanonasis.com'));
603
+ console.log(chalk.gray('2. Navigate to Settings → API Keys'));
604
+ console.log(chalk.gray('3. Click "Generate New Key" and copy the full key value'));
587
605
  console.log();
588
- const { vendorKey } = await inquirer_1.default.prompt([
606
+ const { vendorKey } = await inquirer.prompt([
589
607
  {
590
608
  type: 'password',
591
609
  name: 'vendorKey',
@@ -600,10 +618,10 @@ async function handleVendorKeyFlow(config) {
600
618
  }
601
619
  async function handleOAuthFlow(config) {
602
620
  console.log();
603
- console.log(chalk_1.default.yellow('🌐 Browser-Based OAuth2 Authentication'));
604
- console.log(chalk_1.default.gray('Secure authentication using OAuth2 with PKCE'));
621
+ console.log(chalk.yellow('🌐 Browser-Based OAuth2 Authentication'));
622
+ console.log(chalk.gray('Secure authentication using OAuth2 with PKCE'));
605
623
  console.log();
606
- const { openBrowser } = await inquirer_1.default.prompt([
624
+ const { openBrowser } = await inquirer.prompt([
607
625
  {
608
626
  type: 'confirm',
609
627
  name: 'openBrowser',
@@ -612,41 +630,49 @@ async function handleOAuthFlow(config) {
612
630
  }
613
631
  ]);
614
632
  if (!openBrowser) {
615
- console.log(chalk_1.default.yellow('⚠️ Authentication cancelled'));
633
+ console.log(chalk.yellow('⚠️ Authentication cancelled'));
616
634
  return;
617
635
  }
618
636
  try {
619
637
  // Generate PKCE challenge
620
638
  const pkce = generatePKCE();
621
- console.log(chalk_1.default.gray(' ✓ Generated PKCE challenge'));
639
+ console.log(chalk.gray(' ✓ Generated PKCE challenge'));
622
640
  // Start local callback server
623
641
  const callbackPort = 8888;
624
642
  const callbackPromise = createCallbackServer(callbackPort);
625
- console.log(chalk_1.default.gray(` ✓ Started local callback server on port ${callbackPort}`));
643
+ console.log(chalk.gray(` ✓ Started local callback server on port ${callbackPort}`));
626
644
  // Build OAuth2 authorization URL
627
645
  const authBase = config.getDiscoveredApiUrl();
646
+ const redirectUri = `http://localhost:${callbackPort}/callback`;
628
647
  const authUrl = new URL(`${authBase}/oauth/authorize`);
629
648
  authUrl.searchParams.set('response_type', 'code');
630
649
  authUrl.searchParams.set('client_id', 'lanonasis-cli');
631
- authUrl.searchParams.set('redirect_uri', `http://localhost:${callbackPort}/callback`);
650
+ authUrl.searchParams.set('redirect_uri', redirectUri);
632
651
  authUrl.searchParams.set('scope', 'read write offline_access');
633
652
  authUrl.searchParams.set('code_challenge', pkce.challenge);
634
653
  authUrl.searchParams.set('code_challenge_method', 'S256');
635
- authUrl.searchParams.set('state', crypto_1.default.randomBytes(16).toString('hex'));
654
+ authUrl.searchParams.set('state', crypto.randomBytes(16).toString('hex'));
636
655
  console.log();
637
656
  console.log(colors.info('Opening browser for authentication...'));
638
- await (0, open_1.default)(authUrl.toString());
657
+ await open(authUrl.toString());
639
658
  console.log(colors.info('Waiting for authentication in browser...'));
640
659
  console.log(colors.muted(`If browser doesn't open, visit: ${authUrl.toString()}`));
641
660
  console.log();
642
661
  // Wait for callback
643
- const spinner = (0, ora_1.default)('Waiting for authorization...').start();
662
+ const spinner = ora('Waiting for authorization...').start();
644
663
  const { code } = await callbackPromise;
645
664
  spinner.succeed('Authorization code received');
646
665
  // Exchange code for tokens
647
666
  spinner.text = 'Exchanging code for access tokens...';
648
667
  spinner.start();
649
- const tokens = await exchangeCodeForTokens(code, pkce.verifier, authBase);
668
+ // Debug logging in verbose mode
669
+ if (process.env.CLI_VERBOSE === 'true') {
670
+ console.log(chalk.dim(` Code length: ${code.length}`));
671
+ console.log(chalk.dim(` Verifier length: ${pkce.verifier.length}`));
672
+ console.log(chalk.dim(` Redirect URI: ${redirectUri}`));
673
+ console.log(chalk.dim(` Token endpoint: ${authBase}/oauth/token`));
674
+ }
675
+ const tokens = await exchangeCodeForTokens(code, pkce.verifier, authBase, redirectUri);
650
676
  spinner.succeed('Access tokens received');
651
677
  // Store tokens
652
678
  await config.setToken(tokens.access_token);
@@ -654,27 +680,68 @@ async function handleOAuthFlow(config) {
654
680
  await config.set('token_expires_at', Date.now() + (tokens.expires_in * 1000));
655
681
  await config.set('authMethod', 'oauth2');
656
682
  console.log();
657
- console.log(chalk_1.default.green('✓ OAuth2 authentication successful'));
683
+ console.log(chalk.green('✓ OAuth2 authentication successful'));
658
684
  console.log(colors.info('You can now use Lanonasis services'));
659
685
  process.exit(0);
660
686
  }
661
687
  catch (error) {
662
- console.error(chalk_1.default.red('✖ OAuth2 authentication failed'));
688
+ console.error(chalk.red('✖ OAuth2 authentication failed'));
689
+ // Display detailed error information
663
690
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
664
- console.error(chalk_1.default.gray(` ${errorMessage}`));
691
+ console.error(chalk.gray(` ${errorMessage}`));
692
+ // Show validation details if available
693
+ if (error.details) {
694
+ console.error(chalk.yellow('\n Validation errors:'));
695
+ for (const [field, messages] of Object.entries(error.details)) {
696
+ const msgArray = Array.isArray(messages) ? messages : [messages];
697
+ msgArray.forEach((msg) => {
698
+ console.error(chalk.gray(` • ${field}: ${msg}`));
699
+ });
700
+ }
701
+ }
702
+ // Show error data if available
703
+ if (error.errorData) {
704
+ const errorData = error.errorData;
705
+ if (errorData.error) {
706
+ console.error(chalk.yellow(`\n Error: ${errorData.error}`));
707
+ }
708
+ if (errorData.error_description) {
709
+ console.error(chalk.gray(` ${errorData.error_description}`));
710
+ }
711
+ // Show details if not already shown above
712
+ if (!error.details && errorData.details) {
713
+ console.error(chalk.yellow('\n Details:'));
714
+ console.error(chalk.gray(JSON.stringify(errorData.details, null, 2)));
715
+ }
716
+ }
717
+ // Show full error response in verbose mode
718
+ if (process.env.CLI_VERBOSE === 'true') {
719
+ if (error.response?.data) {
720
+ console.error(chalk.dim('\n Full error response:'));
721
+ console.error(chalk.dim(JSON.stringify(error.response.data, null, 2)));
722
+ }
723
+ if (error.response?.config) {
724
+ console.error(chalk.dim('\n Request config:'));
725
+ console.error(chalk.dim(JSON.stringify({
726
+ url: error.response.config.url,
727
+ method: error.response.config.method,
728
+ data: error.response.config.data
729
+ }, null, 2)));
730
+ }
731
+ }
665
732
  process.exit(1);
666
733
  }
667
734
  }
668
735
  async function handleCredentialsFlow(options, config) {
669
736
  console.log();
670
- console.log(chalk_1.default.yellow('⚙️ Username/Password Authentication'));
737
+ console.log(chalk.yellow('⚙️ Username/Password Authentication'));
671
738
  console.log();
672
739
  // Check for authentication delay before attempting
673
740
  await handleAuthDelay(config);
674
741
  let { email, password } = options;
675
742
  // Get credentials if not provided
676
743
  if (!email || !password) {
677
- const answers = await inquirer_1.default.prompt([
744
+ const answers = await inquirer.prompt([
678
745
  {
679
746
  type: 'input',
680
747
  name: 'email',
@@ -696,14 +763,14 @@ async function handleCredentialsFlow(options, config) {
696
763
  email = answers.email;
697
764
  password = answers.password;
698
765
  }
699
- const spinner = (0, ora_1.default)('Authenticating...').start();
766
+ const spinner = ora('Authenticating...').start();
700
767
  try {
701
- const response = await api_js_1.apiClient.login(email, password);
768
+ const response = await apiClient.login(email, password);
702
769
  // Store token and user info
703
770
  await config.setToken(response.token);
704
771
  spinner.succeed('Login successful');
705
772
  console.log();
706
- console.log(chalk_1.default.green('✓ Authenticated successfully'));
773
+ console.log(chalk.green('✓ Authenticated successfully'));
707
774
  console.log(`Welcome, ${response.user.email}!`);
708
775
  if (response.user.organization_id) {
709
776
  console.log(`Organization: ${response.user.organization_id}`);
@@ -718,7 +785,7 @@ async function handleCredentialsFlow(options, config) {
718
785
  const errorResponse = error && typeof error === 'object' && 'response' in error ? error.response : null;
719
786
  if (errorResponse && typeof errorResponse === 'object' && 'status' in errorResponse && errorResponse.status === 401) {
720
787
  console.log();
721
- const answer = await inquirer_1.default.prompt([
788
+ const answer = await inquirer.prompt([
722
789
  {
723
790
  type: 'confirm',
724
791
  name: 'register',
@@ -736,9 +803,9 @@ async function handleCredentialsFlow(options, config) {
736
803
  }
737
804
  async function registerFlow(defaultEmail) {
738
805
  console.log();
739
- console.log(chalk_1.default.blue.bold('📝 Create New Account'));
806
+ console.log(chalk.blue.bold('📝 Create New Account'));
740
807
  console.log();
741
- const answers = await inquirer_1.default.prompt([
808
+ const answers = await inquirer.prompt([
742
809
  {
743
810
  type: 'input',
744
811
  name: 'email',
@@ -772,14 +839,14 @@ async function registerFlow(defaultEmail) {
772
839
  default: ''
773
840
  }
774
841
  ]);
775
- const spinner = (0, ora_1.default)('Creating account...').start();
842
+ const spinner = ora('Creating account...').start();
776
843
  try {
777
- const response = await api_js_1.apiClient.register(answers.email, answers.password, answers.organizationName || undefined);
778
- const config = new config_js_1.CLIConfig();
844
+ const response = await apiClient.register(answers.email, answers.password, answers.organizationName || undefined);
845
+ const config = new CLIConfig();
779
846
  await config.setToken(response.token);
780
847
  spinner.succeed('Account created successfully');
781
848
  console.log();
782
- console.log(chalk_1.default.green('✓ Account created and authenticated'));
849
+ console.log(chalk.green('✓ Account created and authenticated'));
783
850
  console.log(`Welcome to MaaS, ${response.user.email}!`);
784
851
  if (answers.organizationName) {
785
852
  console.log(`Organization: ${answers.organizationName}`);
@@ -789,7 +856,7 @@ async function registerFlow(defaultEmail) {
789
856
  catch (error) {
790
857
  spinner.fail('Registration failed');
791
858
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
792
- console.error(chalk_1.default.red('✖ Registration failed:'), errorMessage);
859
+ console.error(chalk.red('✖ Registration failed:'), errorMessage);
793
860
  process.exit(1);
794
861
  }
795
862
  }