@hivetechs/hive-ai
Version:
Real-time streaming AI consensus platform with HTTP+SSE MCP integration for Claude Code, VS Code, Cursor, and Windsurf - powered by OpenRouter's unified API
505 lines โข 20.5 kB
JavaScript
/**
* Interactive License Configuration Tool
*
* Restores the license gate functionality that was accidentally removed during OpenRouter simplification.
* Provides interactive prompts for license key input, validation, and tier detection.
*/
import { z } from 'zod';
import * as readline from 'readline';
import { LicenseGate, FeatureTier } from '../../core/license-gate.js';
import { ModernLicenseGate } from '../../core/modern-license-gate.js';
export const licenseConfigurationToolName = 'license_configuration';
export const licenseConfigurationToolDescription = 'Interactive license key configuration and validation';
export const LicenseConfigurationSchema = z.object({
force_reconfigure: z.boolean().default(false).describe('Force reconfiguration even if license exists'),
license_key: z.string().optional().describe('License key to validate (skips interactive prompt)'),
use_modern_gate: z.boolean().default(true).describe('Use modern license gate implementation'),
skip_validation: z.boolean().default(false).describe('Skip backend validation (for testing)')
});
export class LicenseConfigurationWizard {
rl = null;
useModernGate;
externalReadline = false;
constructor(useModernGate = true, existingReadline) {
this.useModernGate = useModernGate;
if (existingReadline) {
this.rl = existingReadline;
this.externalReadline = true;
}
}
initializeReadline() {
if (!this.rl) {
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
}
}
async prompt(question) {
if (!this.rl) {
throw new Error('Readline interface not initialized');
}
return new Promise((resolve) => {
this.rl.question(question, (answer) => {
resolve(answer.trim());
});
});
}
/**
* Main interactive license configuration flow
*/
async configureInteractively(forceReconfigure = false) {
try {
if (!process.stdin.isTTY) {
return {
success: false,
tier: FeatureTier.FREE,
message: 'โ ๏ธ Interactive terminal required for license configuration',
features: [],
error: 'Non-interactive environment detected'
};
}
this.initializeReadline();
// Ensure proper line break before starting
if (forceReconfigure) {
console.log(''); // Extra newline when called from setup wizard
}
console.log('๐ hive-ai License Configuration & Account Management\n');
// Check if license already exists
const hasExistingLicense = await this.checkExistingLicense();
if (hasExistingLicense && !forceReconfigure) {
// Show current user info
try {
const currentStatus = await this.validateExistingLicense();
if (currentStatus.success && currentStatus.user_id) {
console.log('โ
Current account configured!\n');
console.log(`๐ค Current user: ${currentStatus.user_id || 'Unknown'}`);
console.log(`๐ฏ Plan: ${currentStatus.tier} tier\n`);
}
else {
console.log('โ
License key already configured!\n');
}
}
catch (error) {
console.log('โ
License key already configured!\n');
}
const reconfigure = await this.prompt('Would you like to switch to a different account or update your license? (y/N): ');
if (reconfigure.toLowerCase() !== 'y' && reconfigure.toLowerCase() !== 'yes') {
const result = await this.validateExistingLicense();
this.close();
return result;
}
}
// Show license information and pricing only if not forced
if (!forceReconfigure) {
this.showLicenseInformation();
}
// Interactive license key input
const licenseKey = await this.promptForLicenseKey();
if (!licenseKey) {
this.close();
return {
success: false,
tier: FeatureTier.FREE,
message: 'โ License configuration cancelled',
features: [],
error: 'No license key provided'
};
}
// Validate and store license
const result = await this.validateAndStoreLicense(licenseKey);
this.close();
return result;
}
catch (error) {
this.close();
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License configuration failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
features: [],
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
/**
* Non-interactive license validation
*/
async validateLicenseKey(licenseKey, skipValidation = false) {
try {
if (skipValidation) {
// For testing - store without validation
await this.storeLicenseKey(licenseKey);
return {
success: true,
tier: FeatureTier.PREMIUM,
message: 'โ
License key stored (validation skipped for testing)',
features: ['test_mode'],
daily_limit: 1000
};
}
return await this.validateAndStoreLicense(licenseKey);
}
catch (error) {
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
features: [],
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
/**
* Check if license key already exists
*/
async checkExistingLicense() {
try {
const licenseGate = this.getLicenseGate();
// Try to get existing license without validation
if (this.useModernGate && licenseGate instanceof ModernLicenseGate) {
// Modern gate - check encrypted file
return await this.checkModernLicenseFile();
}
else {
// Legacy gate - check config files
return await this.checkLegacyLicenseFiles();
}
}
catch (error) {
return false;
}
}
/**
* Check for modern encrypted license file
*/
async checkModernLicenseFile() {
try {
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const configDir = path.join(os.homedir(), '.hive-ai');
const licenseFile = path.join(configDir, 'license.enc');
return fs.existsSync(licenseFile);
}
catch {
return false;
}
}
/**
* Check for legacy license files
*/
async checkLegacyLicenseFiles() {
try {
const fs = require('fs');
const path = require('path');
const os = require('os');
const homedir = os.homedir();
const legacyPaths = [
path.join(homedir, '.hive-ai', 'license.json'),
path.join(homedir, '.hive-ai', 'config.json'),
path.join(homedir, '.hive-tools', 'license.key')
];
for (const filePath of legacyPaths) {
if (fs.existsSync(filePath)) {
return true;
}
}
return false;
}
catch {
return false;
}
}
/**
* Validate existing license without prompting
*/
async validateExistingLicense() {
try {
const licenseGate = this.getLicenseGate();
const license = await licenseGate.checkFeatureAccess('configure_provider');
return {
success: license.valid,
tier: license.tier,
message: license.valid
? `โ
Existing license validated - ${license.tier} tier`
: `โ Existing license invalid: ${license.message}`,
features: license.features,
daily_limit: license.dailyLimit,
user_id: license.user_id
};
}
catch (error) {
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
features: [],
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
/**
* Show license information and pricing
*/
showLicenseInformation() {
console.log('๐ hive-ai requires a license key to access AI consensus features.\n');
console.log('๐ **FREE TIER**:');
console.log(' โข 10 daily conversations');
console.log(' โข All features included');
console.log('');
console.log('โญ **PREMIUM TIERS**:');
console.log(' โข BASIC: 50 daily conversations');
console.log(' โข STANDARD: 100 daily conversations');
console.log(' โข PREMIUM: 200 daily conversations');
console.log(' โข UNLIMITED: Unlimited conversations');
console.log(' โข All features included');
console.log('');
console.log('๐ก **Get Your License:**');
console.log(' 1. Visit: https://hivetechs.io/pricing');
console.log(' 2. Choose free or premium tier');
console.log(' 3. Get your license key');
console.log(' 4. Enter it below');
console.log('');
}
/**
* Interactive prompt for license key input with full validation
*/
async promptForLicenseKey() {
while (true) {
const licenseKey = await this.prompt('Enter your hive-ai license key (or "skip" for free tier, "help" for more info): ');
if (licenseKey.toLowerCase() === 'skip') {
console.log('\nโ ๏ธ Skipping license configuration.');
console.log('You can configure it later with: hive-ai configure\n');
return null;
}
if (licenseKey.toLowerCase() === 'help') {
console.log('\n๐ **License Help:**');
console.log('โข Free licenses: Get at https://hivetechs.io/pricing (no payment required)');
console.log('โข Premium licenses: Start with 7-day free trial');
console.log('โข License format: HIVE-XXXX-XXXX-XXXX-XXXX (alphanumeric characters)');
console.log('โข Need support? Contact support@hivetechs.io\n');
continue;
}
if (!licenseKey.trim()) {
console.log('โ License key cannot be empty. Please try again or type "skip".\n');
continue;
}
// Basic format validation
if (licenseKey.length < 10) {
console.log('โ License key appears too short. Please check and try again.\n');
continue;
}
// Advanced format validation - moved from validateAndStoreLicense
const isValidFormat = licenseKey.match(/^HIVE-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/);
if (!isValidFormat) {
console.log('โ Invalid license key format. Expected format: HIVE-XXXX-XXXX-XXXX-XXXX-XXXX');
console.log(' Example: HIVE-1234-ABCD-5678-EFGH-IJKL\n');
console.log('๐ก If you need a license key, visit: https://hivetechs.io/pricing\n');
continue;
}
return licenseKey.trim();
}
}
/**
* Validate license with D1 backend and store locally
*/
async validateAndStoreLicense(licenseKey) {
console.log('\n๐ Validating license key with D1 backend...');
try {
// Import required modules
const { saveLicenseKey } = await import('../../subscription/validator.js');
const { initializeDatabase, setUserProfile, clearPendingSyncData } = await import('../../storage/database.js');
const { conversationGateway } = await import('../../auth/conversation-gateway.js');
// Initialize database first
const dbInitialized = await initializeDatabase();
if (dbInitialized) {
console.log('๐๏ธ Database initialized successfully');
}
// PHASE 1: Validate with D1 backend (SERVER-SIDE VALIDATION)
console.log('๐ Validating with server...');
let userProfile;
try {
userProfile = await conversationGateway.validateLicenseKey(licenseKey);
}
catch (error) {
console.log(`โ Server validation failed: ${error.message}\n`);
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License validation failed: ${error.message}`,
features: [],
error: error.message
};
}
// PHASE 2: Store validated profile locally for caching
console.log('๐พ Storing validated profile locally...');
// Store license key in SQLite
await saveLicenseKey(licenseKey, userProfile.email);
console.log('[LicenseGate] License key stored securely');
// Store user profile with server-validated data
await setUserProfile(userProfile.email, licenseKey, userProfile.tier);
// PHASE 3: Clear any pending sync data for previous user
console.log('๐งน Clearing pending sync data...');
await clearPendingSyncData(); // Clear all old pending data
console.log(`๐ค User: ${userProfile.email}`);
console.log(`โ
License validated successfully!`);
console.log(`๐ฏ Tier: ${userProfile.tier.toUpperCase()}`);
console.log(`๐ Daily limit: ${userProfile.dailyLimit} conversations`);
console.log(`๐ Features unlocked: ${userProfile.features.join(', ')}\n`);
return {
success: true,
tier: userProfile.tier,
message: `โ
License configured successfully - ${userProfile.tier} tier activated`,
features: userProfile.features,
daily_limit: userProfile.dailyLimit,
user_id: userProfile.email
};
}
catch (error) {
console.log(`โ Validation error: ${error instanceof Error ? error.message : 'Unknown error'}\n`);
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
features: [],
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
/**
* Store license key securely
*/
async storeLicenseKey(licenseKey) {
const licenseGate = this.getLicenseGate();
await licenseGate.storeLicenseKey(licenseKey);
}
/**
* Get appropriate license gate instance
*/
getLicenseGate() {
if (this.useModernGate) {
return ModernLicenseGate.getInstance();
}
else {
return LicenseGate.getInstance();
}
}
close() {
if (this.rl && !this.externalReadline) {
this.rl.close();
}
}
}
// Tool exports for MCP integration
export async function runLicenseConfigurationTool(args) {
const wizard = new LicenseConfigurationWizard(args.use_modern_gate);
try {
let result;
if (args.license_key) {
// Non-interactive mode with provided license key
result = await wizard.validateLicenseKey(args.license_key, args.skip_validation);
}
else {
// Interactive mode
result = await wizard.configureInteractively(args.force_reconfigure);
}
return {
success: result.success,
tier: result.tier,
message: result.message,
features: result.features,
daily_limit: result.daily_limit,
user_id: result.user_id,
error: result.error
};
}
catch (error) {
return {
success: false,
tier: FeatureTier.FREE,
message: `โ License configuration failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
features: [],
error: error instanceof Error ? error.message : 'Unknown error'
};
}
finally {
wizard.close();
}
}
/**
* Quick license status check
*/
export async function checkLicenseStatus() {
try {
// First try the ModernLicenseGate (file-based)
const licenseGate = ModernLicenseGate.getInstance();
const license = await licenseGate.checkFeatureAccess('setup_wizard');
// Get version from package.json - use hardcoded version for reliability
let version = '1.20.8'; // Current version - update manually when version changes
return {
hasLicense: true,
isValid: license.valid,
tier: license.tier,
email: license.email,
version,
message: license.valid
? `License active - ${license.tier} tier`
: `License invalid: ${license.message}`
};
}
catch (error) {
// Fallback: Check database storage
try {
const { getConfig } = await import('../../storage/unified-database.js');
const licenseKey = await getConfig('license_key');
if (licenseKey && licenseKey.startsWith('HIVE-')) {
// We have a license key in database, but primary validation failed
// This likely means the license is invalid or expired
return {
hasLicense: true,
isValid: false,
tier: FeatureTier.FREE,
message: 'License key found but validation failed'
};
}
}
catch (dbError) {
// Database check failed, continue to no license found
}
return {
hasLicense: false,
isValid: false,
tier: FeatureTier.FREE,
message: 'No license configured'
};
}
}
/**
* CLI helper for license configuration
*/
export async function configureLicenseFromCLI() {
const wizard = new LicenseConfigurationWizard();
try {
const result = await wizard.configureInteractively();
if (result.success) {
console.log('\n๐ Account setup complete!');
if (result.user_id) {
console.log(`๐ค Logged in as: ${result.user_id}`);
console.log(`๐ฏ Plan: ${result.tier} tier`);
}
console.log('You can now use all hive-ai features.');
console.log('\n๐ก Commands:');
console.log(' hive logout # Switch to different account');
console.log(' hive quickstart # Complete setup');
}
else {
console.log('\n๐ก Account setup incomplete.');
console.log('You can try again anytime with: hive login');
}
}
catch (error) {
console.error(`\nโ Configuration error: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
//# sourceMappingURL=license-configuration.js.map