UNPKG

@lanonasis/cli

Version:

Professional CLI for LanOnasis Memory as a Service (MaaS) with MCP support, seamless inline editing, and enterprise-grade security

449 lines (448 loc) 18.9 kB
import chalk from 'chalk'; import inquirer from 'inquirer'; import { CLIConfig } from '../utils/config.js'; import { apiClient } from '../utils/api.js'; // Color scheme const colors = { primary: chalk.blue.bold, success: chalk.green, warning: chalk.yellow, error: chalk.red, info: chalk.cyan, accent: chalk.magenta, muted: chalk.gray, highlight: chalk.white.bold }; export class UserGuidanceSystem { config; steps = []; constructor() { this.config = new CLIConfig(); this.initializeSteps(); } initializeSteps() { this.steps = [ { id: 'initialization', title: 'Initialize Configuration', description: 'Set up your CLI configuration and preferences', action: this.initializeConfig.bind(this) }, { id: 'authentication', title: 'Authentication Setup', description: 'Connect to your Onasis-Core account using preferred method', action: this.setupAuthentication.bind(this) }, { id: 'verification', title: 'Connection Verification', description: 'Verify your connection to Onasis-Core services', action: this.verifyConnection.bind(this) }, { id: 'first_memory', title: 'Create Your First Memory', description: 'Learn how to store and retrieve information', action: this.createFirstMemory.bind(this), optional: true }, { id: 'explore_features', title: 'Explore Advanced Features', description: 'Discover topics, MCP integration, and advanced workflows', action: this.exploreFeatures.bind(this), optional: true }, { id: 'productivity_tips', title: 'Productivity Setup', description: 'Set up shell completions and aliases for efficient usage', action: this.setupProductivity.bind(this), optional: true } ]; } async runGuidedSetup() { console.log(chalk.blue.bold('🚀 Welcome to Onasis-Core CLI Setup Guide')); console.log(colors.info('═'.repeat(50))); console.log(); console.log(colors.highlight('This guided setup will help you get started with enterprise-grade')); console.log(colors.highlight('Memory as a Service and API management capabilities.')); console.log(); // Check current status await this.assessCurrentStatus(); const { proceedWithGuide } = await inquirer.prompt([ { type: 'confirm', name: 'proceedWithGuide', message: 'Would you like to proceed with the guided setup?', default: true } ]); if (!proceedWithGuide) { console.log(chalk.yellow('Setup cancelled. You can run this guide anytime with:')); console.log(chalk.cyan(' lanonasis guide')); return; } // Run through steps for (const step of this.steps) { if (step.completed) { console.log(chalk.green(`✅ ${step.title} (already completed)`)); continue; } await this.executeStep(step); } await this.showCompletionSummary(); } async assessCurrentStatus() { console.log(chalk.yellow('📋 Checking current setup status...')); console.log(); // Check configuration const configExists = await this.config.exists(); if (configExists) { this.markStepCompleted('initialization'); console.log(chalk.green('✅ Configuration found')); } else { console.log(chalk.gray('⏳ Configuration needs setup')); } // Check authentication const isAuthenticated = await this.config.isAuthenticated(); const hasVendorKey = this.config.hasVendorKey(); if (isAuthenticated || hasVendorKey) { this.markStepCompleted('authentication'); console.log(chalk.green(`✅ Authentication configured (${hasVendorKey ? 'vendor key' : 'JWT token'})`)); } else { console.log(chalk.gray('⏳ Authentication needs setup')); } // Check connection try { await apiClient.get('/health'); this.markStepCompleted('verification'); console.log(chalk.green('✅ Service connection verified')); } catch { console.log(chalk.gray('⏳ Service connection needs verification')); } console.log(); } markStepCompleted(stepId) { const step = this.steps.find(s => s.id === stepId); if (step) { step.completed = true; } } async executeStep(step) { console.log(chalk.blue.bold(`🔧 ${step.title}`)); console.log(colors.info('─'.repeat(30))); console.log(chalk.white(step.description)); console.log(); if (step.optional) { const { proceed } = await inquirer.prompt([ { type: 'confirm', name: 'proceed', message: `Execute this optional step: ${step.title}?`, default: true } ]); if (!proceed) { console.log(chalk.yellow('⏭️ Skipped')); console.log(); return; } } if (step.action) { try { await step.action(); step.completed = true; console.log(chalk.green(`✅ ${step.title} completed successfully`)); } catch (error) { console.log(chalk.red(`❌ ${step.title} failed`)); console.log(chalk.gray(error instanceof Error ? error.message : String(error))); const { retry } = await inquirer.prompt([ { type: 'confirm', name: 'retry', message: 'Would you like to retry this step?', default: true } ]); if (retry) { await this.executeStep(step); // Recursive retry } } } console.log(); } async initializeConfig() { console.log(colors.info('Initializing CLI configuration...')); const { apiUrl, outputFormat } = await inquirer.prompt([ { type: 'input', name: 'apiUrl', message: 'API URL (press Enter for default):', default: 'https://api.lanonasis.com/api/v1' }, { type: 'select', name: 'outputFormat', message: 'Preferred output format:', choices: ['table', 'json', 'yaml', 'csv'], default: 'table' } ]); await this.config.init(); await this.config.setApiUrl(apiUrl); await this.config.setAndSave('defaultOutputFormat', outputFormat); console.log(colors.success('Configuration initialized successfully')); } async setupAuthentication() { console.log(colors.info('Setting up authentication...')); console.log(chalk.gray('Choose the authentication method that best fits your use case:')); console.log(); const { authMethod } = await inquirer.prompt([ { type: 'select', name: 'authMethod', message: 'Choose authentication method:', choices: [ { name: '🔑 Vendor Key (Recommended for API integration)', value: 'vendor_key', short: 'Vendor Key' }, { name: '🌐 OAuth (Browser-based authentication)', value: 'oauth', short: 'OAuth' }, { name: '📧 Username/Password (Direct credentials)', value: 'credentials', short: 'Credentials' } ] } ]); // Import and call the login command with the chosen method const { loginCommand } = await import('./auth.js'); switch (authMethod) { case 'vendor_key': console.log(chalk.yellow('📝 Vendor keys provide secure, programmatic access')); console.log(chalk.gray('Find it in your dashboard under API Keys.')); console.log(); break; case 'oauth': console.log(chalk.yellow('🌐 OAuth provides secure browser-based authentication')); console.log(chalk.gray('Your browser will open for authentication')); console.log(); break; case 'credentials': console.log(chalk.yellow('📧 Direct authentication with your account')); console.log(); break; } // This will be handled by the enhanced auth command await loginCommand({}); } async verifyConnection() { console.log(colors.info('Verifying connection to Onasis-Core services...')); try { const health = await apiClient.get('/health'); console.log(colors.success('✅ Connection verified successfully')); console.log(chalk.gray(`Server status: ${health.status}`)); console.log(chalk.gray(`Server version: ${health.version}`)); } catch (error) { throw new Error(`Connection verification failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async createFirstMemory() { console.log(colors.info('Creating your first memory entry...')); console.log(chalk.gray('Memories are the core of the MaaS platform - they store and organize information')); console.log(); const { createSample } = await inquirer.prompt([ { type: 'confirm', name: 'createSample', message: 'Create a sample memory to get started?', default: true } ]); if (createSample) { try { const memory = await apiClient.createMemory({ title: 'Welcome to Onasis-Core', content: 'This is your first memory in the Onasis-Core MaaS platform. You can store, search, and organize information efficiently using memories.', memory_type: 'reference', tags: ['welcome', 'getting-started', 'onasis-core'] }); console.log(colors.success('✅ Sample memory created successfully')); console.log(chalk.gray(`Memory ID: ${memory.id}`)); console.log(); console.log(colors.info('💡 Try these commands to explore:')); console.log(chalk.cyan(' lanonasis memory list')); console.log(chalk.cyan(' lanonasis memory search "welcome"')); } catch (error) { throw new Error(`Failed to create sample memory: ${error instanceof Error ? error.message : 'Unknown error'}`); } } else { console.log(colors.info('💡 You can create memories anytime with:')); console.log(chalk.cyan(' lanonasis memory create --title "My Title" --content "Content"')); } } async exploreFeatures() { console.log(colors.info('🎯 Advanced Features Overview')); console.log(); const features = [ { name: 'Topics', description: 'Organize memories into categories', command: 'lanonasis topic create --name "My Project"' }, { name: 'MCP Integration', description: 'Model Context Protocol for AI interactions', command: 'lanonasis mcp status' }, { name: 'API Key Management', description: 'Create and manage API keys for integrations', command: 'lanonasis api-keys list' }, { name: 'Memory Search', description: 'Semantic search across all memories', command: 'lanonasis memory search "your query"' } ]; console.log(chalk.yellow('📚 Available Features:')); features.forEach((feature, index) => { console.log(`${index + 1}. ${colors.accent(feature.name)}: ${feature.description}`); console.log(` ${chalk.cyan(feature.command)}`); console.log(); }); console.log(colors.info('💡 Run any command with --help to learn more')); } async setupProductivity() { console.log(colors.info('🚀 Productivity Setup')); console.log(); const { shell } = await inquirer.prompt([ { type: 'select', name: 'shell', message: 'Which shell do you use?', choices: [ { name: 'Bash', value: 'bash' }, { name: 'Zsh', value: 'zsh' }, { name: 'Fish', value: 'fish' }, { name: 'Other / Skip', value: 'skip' } ] } ]); if (shell !== 'skip') { console.log(chalk.yellow(`📝 Shell Completion Setup (${shell}):`)); console.log(); switch (shell) { case 'bash': console.log(colors.info('Add to your ~/.bashrc:')); console.log(chalk.cyan(' source <(lanonasis --completion bash)')); break; case 'zsh': console.log(colors.info('Add to your ~/.zshrc:')); console.log(chalk.cyan(' source <(lanonasis --completion zsh)')); break; case 'fish': console.log(colors.info('Add to your ~/.config/fish/config.fish:')); console.log(chalk.cyan(' lanonasis --completion fish | source')); break; } console.log(); console.log(colors.success('✅ Completions will provide tab completion for all commands')); } console.log(); console.log(chalk.yellow('🔗 Useful Aliases:')); console.log(colors.info('You can also use these command aliases:')); console.log(chalk.cyan(' onasis # Same as lanonasis (Golden Contract compliant)')); console.log(chalk.cyan(' memory # Direct memory management')); console.log(chalk.cyan(' maas # MaaS-focused interface')); } async showCompletionSummary() { console.log(chalk.blue.bold('🎉 Setup Complete!')); console.log(colors.info('═'.repeat(30))); console.log(); const completedSteps = this.steps.filter(s => s.completed); const totalSteps = this.steps.filter(s => !s.optional).length; const completedRequired = completedSteps.filter(s => !s.optional).length; console.log(colors.success(`✅ Completed ${completedRequired}/${totalSteps} required steps`)); if (completedSteps.some(s => s.optional)) { console.log(colors.info(`📚 Plus ${completedSteps.filter(s => s.optional).length} optional steps`)); } console.log(); console.log(chalk.yellow('🚀 You\'re ready to use Onasis-Core CLI!')); console.log(); console.log(colors.info('Next steps:')); console.log(chalk.cyan(' lanonasis health # Check system status')); console.log(chalk.cyan(' lanonasis memory list # View your memories')); console.log(chalk.cyan(' lanonasis --help # Explore all commands')); console.log(); console.log(chalk.gray('💡 Need help? Visit: https://docs.lanonasis.com/cli')); console.log(chalk.gray('🌐 Dashboard: https://api.lanonasis.com/dashboard')); } } export async function guideCommand() { const guide = new UserGuidanceSystem(); await guide.runGuidedSetup(); } export async function quickStartCommand() { console.log(chalk.blue.bold('⚡ Onasis-Core CLI Quick Start')); console.log(colors.info('═'.repeat(30))); console.log(); const essentialCommands = [ { category: 'Setup', commands: [ { cmd: 'lanonasis init', desc: 'Initialize configuration' }, { cmd: 'lanonasis login --vendor-key <your-key>', desc: 'Authenticate with vendor key' }, { cmd: 'lanonasis health', desc: 'Verify system health' } ] }, { category: 'Memory Management', commands: [ { cmd: 'lanonasis memory create --title "Title" --content "Content"', desc: 'Create memory' }, { cmd: 'lanonasis memory list', desc: 'List all memories' }, { cmd: 'lanonasis memory search "query"', desc: 'Search memories' } ] }, { category: 'Advanced', commands: [ { cmd: 'lanonasis topic create --name "Project"', desc: 'Create topic' }, { cmd: 'lanonasis mcp status', desc: 'Check MCP server' }, { cmd: 'lanonasis api-keys list', desc: 'Manage API keys' }, { cmd: 'lanonasis prescan run <path> --ci', desc: 'Prescan filesystem for secrets/PII' }, { cmd: 'lanonasis prescan status', desc: 'Show the latest saved prescan report summary' } ] } ]; essentialCommands.forEach(category => { console.log(colors.accent(`📁 ${category.category}:`)); category.commands.forEach(({ cmd, desc }) => { console.log(` ${chalk.cyan(cmd)}`); console.log(` ${chalk.gray(desc)}`); console.log(); }); }); console.log(colors.info('💡 Pro Tips:')); console.log(chalk.gray(' • Use --help with any command for detailed options')); console.log(chalk.gray(' • Set up shell completions: lanonasis completion')); console.log(chalk.gray(' • Use --verbose for detailed operation logs')); console.log(); }