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