aios-core 4.2.1 → 4.2.3
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.
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 4.2.
|
|
11
|
-
generated_at: "2026-02-16T00:
|
|
10
|
+
version: 4.2.3
|
|
11
|
+
generated_at: "2026-02-16T00:47:03.699Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
13
|
file_count: 992
|
|
14
14
|
files:
|
package/package.json
CHANGED
|
@@ -264,13 +264,18 @@ async function stepLicenseGateCI(options) {
|
|
|
264
264
|
/**
|
|
265
265
|
* Interactive email/password license gate flow.
|
|
266
266
|
*
|
|
267
|
-
*
|
|
267
|
+
* New flow (PRO-11 v2):
|
|
268
|
+
* 1. Email → checkEmail API → { isBuyer, hasAccount }
|
|
269
|
+
* 2. NOT buyer → "No Pro access found" → STOP
|
|
270
|
+
* 3. IS buyer + HAS account → Password → Login (with retry) → Activate
|
|
271
|
+
* 4. IS buyer + NO account → Password + Confirm → Signup → Verify email → Login → Activate
|
|
268
272
|
*
|
|
269
273
|
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
270
274
|
*/
|
|
271
275
|
async function stepLicenseGateWithEmail() {
|
|
272
276
|
const inquirer = require('inquirer');
|
|
273
277
|
|
|
278
|
+
// Step 1: Get email
|
|
274
279
|
const { email } = await inquirer.prompt([
|
|
275
280
|
{
|
|
276
281
|
type: 'input',
|
|
@@ -288,53 +293,147 @@ async function stepLicenseGateWithEmail() {
|
|
|
288
293
|
},
|
|
289
294
|
]);
|
|
290
295
|
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
const trimmedEmail = email.trim();
|
|
297
|
+
|
|
298
|
+
// Step 2: Check buyer status + account existence
|
|
299
|
+
const loader = module.exports._testing ? module.exports._testing.loadLicenseApi : loadLicenseApi;
|
|
300
|
+
const licenseModule = loader();
|
|
301
|
+
|
|
302
|
+
if (!licenseModule) {
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
error: 'Pro license module not available. Ensure @aios-fullstack/pro is installed.',
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const { LicenseApiClient } = licenseModule;
|
|
310
|
+
const client = new LicenseApiClient();
|
|
311
|
+
|
|
312
|
+
// Check connectivity
|
|
313
|
+
const online = await client.isOnline();
|
|
314
|
+
if (!online) {
|
|
315
|
+
return {
|
|
316
|
+
success: false,
|
|
317
|
+
error: 'License server is unreachable. Check your internet connection and try again.',
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const checkSpinner = createSpinner('Verifying your access...');
|
|
322
|
+
checkSpinner.start();
|
|
323
|
+
|
|
324
|
+
let checkResult;
|
|
325
|
+
try {
|
|
326
|
+
checkResult = await client.checkEmail(trimmedEmail);
|
|
327
|
+
} catch (checkError) {
|
|
328
|
+
checkSpinner.fail(`Verification failed: ${checkError.message}`);
|
|
329
|
+
return { success: false, error: checkError.message };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Step 2a: NOT a buyer → stop
|
|
333
|
+
if (!checkResult.isBuyer) {
|
|
334
|
+
checkSpinner.fail('No AIOS Pro access found for this email.');
|
|
335
|
+
console.log('');
|
|
336
|
+
showInfo('If you believe this is an error, please contact support:');
|
|
337
|
+
showInfo(' Email: support@synkra.ai');
|
|
338
|
+
showInfo(' Purchase Pro: https://pro.synkra.ai');
|
|
339
|
+
return { success: false, error: 'Email not found in Pro buyers list.' };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Step 2b: IS a buyer
|
|
343
|
+
if (checkResult.hasAccount) {
|
|
344
|
+
checkSpinner.succeed('Pro access confirmed! Account found.');
|
|
345
|
+
// Flow 3: Existing account → Login with password (retry loop)
|
|
346
|
+
return loginWithRetry(client, trimmedEmail);
|
|
347
|
+
}
|
|
305
348
|
|
|
306
|
-
|
|
349
|
+
checkSpinner.succeed('Pro access confirmed! Let\'s create your account.');
|
|
350
|
+
// Flow 4: New account → Create account flow
|
|
351
|
+
return createAccountFlow(client, trimmedEmail);
|
|
307
352
|
}
|
|
308
353
|
|
|
309
354
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* Asks for confirmation, then password with confirmation.
|
|
313
|
-
* Calls signup API and logs in to get session token.
|
|
355
|
+
* Login flow with password retry (max 3 attempts).
|
|
314
356
|
*
|
|
315
357
|
* @param {object} client - LicenseApiClient instance
|
|
316
|
-
* @param {string} email -
|
|
317
|
-
* @returns {Promise<Object>} Result with { success,
|
|
358
|
+
* @param {string} email - Verified buyer email
|
|
359
|
+
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
318
360
|
*/
|
|
319
|
-
async function
|
|
361
|
+
async function loginWithRetry(client, email) {
|
|
320
362
|
const inquirer = require('inquirer');
|
|
321
363
|
|
|
322
|
-
|
|
323
|
-
|
|
364
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
365
|
+
const { password } = await inquirer.prompt([
|
|
366
|
+
{
|
|
367
|
+
type: 'password',
|
|
368
|
+
name: 'password',
|
|
369
|
+
message: colors.primary('Password:'),
|
|
370
|
+
mask: '*',
|
|
371
|
+
validate: (input) => {
|
|
372
|
+
if (!input || input.length < MIN_PASSWORD_LENGTH) {
|
|
373
|
+
return `Password must be at least ${MIN_PASSWORD_LENGTH} characters`;
|
|
374
|
+
}
|
|
375
|
+
return true;
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
]);
|
|
324
379
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
380
|
+
const spinner = createSpinner('Authenticating...');
|
|
381
|
+
spinner.start();
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const loginResult = await client.login(email, password);
|
|
385
|
+
spinner.succeed('Authenticated successfully.');
|
|
386
|
+
|
|
387
|
+
// Wait for email verification if needed
|
|
388
|
+
if (!loginResult.emailVerified) {
|
|
389
|
+
const verifyResult = await waitForEmailVerification(client, loginResult.sessionToken);
|
|
390
|
+
if (!verifyResult.success) {
|
|
391
|
+
return verifyResult;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
333
394
|
|
|
334
|
-
|
|
335
|
-
|
|
395
|
+
// Activate Pro
|
|
396
|
+
return activateProByAuth(client, loginResult.sessionToken);
|
|
397
|
+
} catch (loginError) {
|
|
398
|
+
if (loginError.code === 'INVALID_CREDENTIALS') {
|
|
399
|
+
const remaining = MAX_RETRIES - attempt;
|
|
400
|
+
if (remaining > 0) {
|
|
401
|
+
spinner.fail(`Incorrect password. ${remaining} attempt${remaining > 1 ? 's' : ''} remaining.`);
|
|
402
|
+
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password');
|
|
403
|
+
} else {
|
|
404
|
+
spinner.fail('Maximum login attempts reached.');
|
|
405
|
+
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password');
|
|
406
|
+
showInfo('Or contact support: support@synkra.ai');
|
|
407
|
+
return { success: false, error: 'Maximum login attempts reached.' };
|
|
408
|
+
}
|
|
409
|
+
} else if (loginError.code === 'AUTH_RATE_LIMITED') {
|
|
410
|
+
spinner.fail(loginError.message);
|
|
411
|
+
return { success: false, error: loginError.message };
|
|
412
|
+
} else {
|
|
413
|
+
spinner.fail(`Authentication failed: ${loginError.message}`);
|
|
414
|
+
return { success: false, error: loginError.message };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
336
417
|
}
|
|
337
418
|
|
|
419
|
+
return { success: false, error: 'Maximum login attempts reached.' };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Create account flow for new buyers.
|
|
424
|
+
*
|
|
425
|
+
* Asks for password, creates account, waits for email verification.
|
|
426
|
+
*
|
|
427
|
+
* @param {object} client - LicenseApiClient instance
|
|
428
|
+
* @param {string} email - Verified buyer email
|
|
429
|
+
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
430
|
+
*/
|
|
431
|
+
async function createAccountFlow(client, email) {
|
|
432
|
+
const inquirer = require('inquirer');
|
|
433
|
+
|
|
434
|
+
console.log('');
|
|
435
|
+
showInfo('Create your AIOS Pro account to get started.');
|
|
436
|
+
|
|
338
437
|
// Ask for password with confirmation
|
|
339
438
|
const { newPassword } = await inquirer.prompt([
|
|
340
439
|
{
|
|
@@ -370,29 +469,79 @@ async function promptCreateAccount(client, email) {
|
|
|
370
469
|
const spinner = createSpinner('Creating account...');
|
|
371
470
|
spinner.start();
|
|
372
471
|
|
|
472
|
+
let sessionToken;
|
|
373
473
|
try {
|
|
374
474
|
await client.signup(email, confirmPassword);
|
|
375
475
|
spinner.succeed('Account created! Verification email sent.');
|
|
376
|
-
|
|
377
|
-
// Login to get session token
|
|
378
|
-
const loginResult = await client.login(email, confirmPassword);
|
|
379
|
-
return { success: true, sessionToken: loginResult.sessionToken };
|
|
380
476
|
} catch (signupError) {
|
|
381
477
|
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
382
|
-
spinner.
|
|
383
|
-
|
|
384
|
-
return { success: false, error: signupError.message };
|
|
478
|
+
spinner.info('Account already exists. Switching to login...');
|
|
479
|
+
return loginWithRetry(client, email);
|
|
385
480
|
}
|
|
386
481
|
spinner.fail(`Account creation failed: ${signupError.message}`);
|
|
387
482
|
return { success: false, error: signupError.message };
|
|
388
483
|
}
|
|
484
|
+
|
|
485
|
+
// Wait for email verification
|
|
486
|
+
console.log('');
|
|
487
|
+
showInfo('Please check your email and click the verification link.');
|
|
488
|
+
|
|
489
|
+
// Login after signup to get session token
|
|
490
|
+
try {
|
|
491
|
+
const loginResult = await client.login(email, confirmPassword);
|
|
492
|
+
sessionToken = loginResult.sessionToken;
|
|
493
|
+
} catch {
|
|
494
|
+
// Login might fail if email not verified yet — that's OK, we'll poll
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (sessionToken) {
|
|
498
|
+
const verifyResult = await waitForEmailVerification(client, sessionToken);
|
|
499
|
+
if (!verifyResult.success) {
|
|
500
|
+
return verifyResult;
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
// Need to wait for verification then login
|
|
504
|
+
showInfo('Waiting for email verification...');
|
|
505
|
+
showInfo('After verifying, the installation will continue automatically.');
|
|
506
|
+
|
|
507
|
+
// Poll by trying to login periodically
|
|
508
|
+
const startTime = Date.now();
|
|
509
|
+
while (Date.now() - startTime < VERIFY_POLL_TIMEOUT_MS) {
|
|
510
|
+
await new Promise((resolve) => setTimeout(resolve, VERIFY_POLL_INTERVAL_MS));
|
|
511
|
+
try {
|
|
512
|
+
const loginResult = await client.login(email, confirmPassword);
|
|
513
|
+
sessionToken = loginResult.sessionToken;
|
|
514
|
+
if (loginResult.emailVerified) {
|
|
515
|
+
showSuccess('Email verified!');
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
// Got session but not verified yet — use the verification polling
|
|
519
|
+
const verifyResult = await waitForEmailVerification(client, sessionToken);
|
|
520
|
+
if (!verifyResult.success) {
|
|
521
|
+
return verifyResult;
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
} catch {
|
|
525
|
+
// Still waiting for verification
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (!sessionToken) {
|
|
530
|
+
showError('Email verification timed out after 10 minutes.');
|
|
531
|
+
showInfo('Run the installer again to retry.');
|
|
532
|
+
return { success: false, error: 'Email verification timed out.' };
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Activate Pro
|
|
537
|
+
return activateProByAuth(client, sessionToken);
|
|
389
538
|
}
|
|
390
539
|
|
|
391
540
|
/**
|
|
392
|
-
* Authenticate with email and password.
|
|
541
|
+
* Authenticate with email and password (CI mode / pre-provided credentials).
|
|
393
542
|
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
543
|
+
* For interactive mode, use stepLicenseGateWithEmail() instead (buyer-first flow).
|
|
544
|
+
* This function is used when credentials are pre-provided (CI, CLI args).
|
|
396
545
|
*
|
|
397
546
|
* @param {string} email - User email
|
|
398
547
|
* @param {string} password - User password
|
|
@@ -421,7 +570,22 @@ async function authenticateWithEmail(email, password) {
|
|
|
421
570
|
};
|
|
422
571
|
}
|
|
423
572
|
|
|
424
|
-
//
|
|
573
|
+
// CI mode: check buyer first, then try login or auto-signup
|
|
574
|
+
const checkSpinner = createSpinner('Verifying access...');
|
|
575
|
+
checkSpinner.start();
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
const checkResult = await client.checkEmail(email);
|
|
579
|
+
if (!checkResult.isBuyer) {
|
|
580
|
+
checkSpinner.fail('No AIOS Pro access found for this email.');
|
|
581
|
+
return { success: false, error: 'Email not found in Pro buyers list.' };
|
|
582
|
+
}
|
|
583
|
+
checkSpinner.succeed('Pro access confirmed.');
|
|
584
|
+
} catch {
|
|
585
|
+
checkSpinner.info('Buyer check unavailable, proceeding with login...');
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Try login
|
|
425
589
|
const spinner = createSpinner('Authenticating...');
|
|
426
590
|
spinner.start();
|
|
427
591
|
|
|
@@ -434,44 +598,31 @@ async function authenticateWithEmail(email, password) {
|
|
|
434
598
|
emailVerified = loginResult.emailVerified;
|
|
435
599
|
spinner.succeed('Authenticated successfully.');
|
|
436
600
|
} catch (loginError) {
|
|
437
|
-
// If invalid credentials, offer to create account
|
|
438
601
|
if (loginError.code === 'INVALID_CREDENTIALS') {
|
|
439
|
-
spinner.info('
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
try {
|
|
444
|
-
await client.signup(email, password);
|
|
445
|
-
showSuccess('Account created. Verification email sent!');
|
|
446
|
-
emailVerified = false;
|
|
447
|
-
const loginAfterSignup = await client.login(email, password);
|
|
448
|
-
sessionToken = loginAfterSignup.sessionToken;
|
|
449
|
-
} catch (signupError) {
|
|
450
|
-
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
451
|
-
showError('An account exists with this email but the password is incorrect.');
|
|
452
|
-
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password or contact support@synkra.ai');
|
|
453
|
-
return { success: false, error: signupError.message };
|
|
454
|
-
}
|
|
455
|
-
return { success: false, error: signupError.message };
|
|
456
|
-
}
|
|
457
|
-
} else {
|
|
458
|
-
// Interactive: ask user if they want to create account
|
|
459
|
-
const signupResult = await promptCreateAccount(client, email);
|
|
460
|
-
if (!signupResult.success) {
|
|
461
|
-
return signupResult;
|
|
462
|
-
}
|
|
463
|
-
sessionToken = signupResult.sessionToken;
|
|
602
|
+
spinner.info('Login failed, attempting signup...');
|
|
603
|
+
try {
|
|
604
|
+
await client.signup(email, password);
|
|
605
|
+
showSuccess('Account created. Verification email sent!');
|
|
464
606
|
emailVerified = false;
|
|
607
|
+
const loginAfterSignup = await client.login(email, password);
|
|
608
|
+
sessionToken = loginAfterSignup.sessionToken;
|
|
609
|
+
} catch (signupError) {
|
|
610
|
+
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
611
|
+
showError('Account exists but the password is incorrect.');
|
|
612
|
+
return { success: false, error: 'Invalid password.' };
|
|
613
|
+
}
|
|
614
|
+
return { success: false, error: signupError.message };
|
|
465
615
|
}
|
|
466
|
-
} else if (loginError.code === 'AUTH_RATE_LIMITED') {
|
|
467
|
-
spinner.fail(loginError.message);
|
|
468
|
-
return { success: false, error: loginError.message };
|
|
469
616
|
} else {
|
|
470
617
|
spinner.fail(`Authentication failed: ${loginError.message}`);
|
|
471
618
|
return { success: false, error: loginError.message };
|
|
472
619
|
}
|
|
473
620
|
}
|
|
474
621
|
|
|
622
|
+
if (!sessionToken) {
|
|
623
|
+
return { success: false, error: 'Authentication failed.' };
|
|
624
|
+
}
|
|
625
|
+
|
|
475
626
|
// Wait for email verification if needed
|
|
476
627
|
if (!emailVerified) {
|
|
477
628
|
const verifyResult = await waitForEmailVerification(client, sessionToken);
|
|
@@ -1005,11 +1156,12 @@ module.exports = {
|
|
|
1005
1156
|
authenticateWithEmail,
|
|
1006
1157
|
waitForEmailVerification,
|
|
1007
1158
|
activateProByAuth,
|
|
1159
|
+
loginWithRetry,
|
|
1160
|
+
createAccountFlow,
|
|
1008
1161
|
stepLicenseGateCI,
|
|
1009
1162
|
stepLicenseGateWithKey,
|
|
1010
1163
|
stepLicenseGateWithKeyInteractive,
|
|
1011
1164
|
stepLicenseGateWithEmail,
|
|
1012
|
-
promptCreateAccount,
|
|
1013
1165
|
loadLicenseApi,
|
|
1014
1166
|
loadFeatureGate,
|
|
1015
1167
|
loadProScaffolder,
|