UNPKG

@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
/** * 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