UNPKG

@lanonasis/cli

Version:

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

356 lines (355 loc) 11.3 kB
/** * Core Architecture for Enhanced CLI Experience * Implements the layered architecture for state management, interaction, and presentation */ import { EventEmitter } from 'events'; import chalk from 'chalk'; // State Management Layer export class StateManager extends EventEmitter { navigationStack = []; userContext; sessionMemory; preferences; constructor() { super(); this.userContext = this.initializeUserContext(); this.sessionMemory = this.initializeSessionMemory(); this.preferences = this.loadPreferences(); } initializeUserContext() { return { preferences: this.loadPreferences(), sessionStarted: new Date(), history: [] }; } initializeSessionMemory() { return { recentCommands: [], recentMemories: [], searchHistory: [], clipboardHistory: [], undoStack: [] }; } loadPreferences() { // Load from config file or use defaults return { theme: 'default', outputFormat: 'table', verbosity: 'normal', expertMode: false, shortcuts: true, animations: true, autoComplete: true, confirmDestructive: true }; } // Navigation methods pushNavigation(state) { this.navigationStack.push(state); this.emit('navigation:push', state); this.renderBreadcrumb(); } popNavigation() { if (this.navigationStack.length > 1) { const state = this.navigationStack.pop(); this.emit('navigation:pop', state); this.renderBreadcrumb(); return state; } return undefined; } getCurrentNavigation() { return this.navigationStack[this.navigationStack.length - 1]; } renderBreadcrumb() { if (this.navigationStack.length > 0) { const path = this.navigationStack.map(s => s.name).join(' > '); console.log(chalk.dim(path)); } } // Context methods updateUserContext(updates) { this.userContext = { ...this.userContext, ...updates }; this.emit('context:update', this.userContext); } getUserContext() { return this.userContext; } // Session memory methods addToHistory(command) { this.sessionMemory.recentCommands.push(command); if (this.sessionMemory.recentCommands.length > 100) { this.sessionMemory.recentCommands.shift(); } this.userContext.history.push(command); } getRecentCommands(limit = 10) { return this.sessionMemory.recentCommands.slice(-limit); } // Preferences methods updatePreference(key, value) { this.preferences[key] = value; this.savePreferences(); this.emit('preferences:update', { key, value }); } getPreferences() { return this.preferences; } savePreferences() { // Save to config file // Implementation would write to ~/.onasis/preferences.json } // Undo/Redo functionality pushToUndoStack(action) { this.sessionMemory.undoStack.push(action); if (this.sessionMemory.undoStack.length > 50) { this.sessionMemory.undoStack.shift(); } } popFromUndoStack() { return this.sessionMemory.undoStack.pop(); } } // Interaction Engine export class InteractionEngine { stateManager; promptSystem; validationEngine; feedbackLoop; helpSystem; constructor(stateManager) { this.stateManager = stateManager; this.promptSystem = new AdaptivePromptSystem(stateManager); this.validationEngine = new ContextualValidator(); this.feedbackLoop = new RealTimeFeedback(); this.helpSystem = new InlineHelpProvider(stateManager); } async prompt(config) { return this.promptSystem.prompt(config); } validate(value, rules) { return this.validationEngine.validate(value, rules); } showFeedback(message, type) { this.feedbackLoop.show(message, type); } getContextualHelp() { return this.helpSystem.getHelp(); } } // Adaptive Prompt System export class AdaptivePromptSystem { stateManager; constructor(stateManager) { this.stateManager = stateManager; } async prompt(config) { const preferences = this.stateManager.getPreferences(); // Adapt prompt based on user preferences and context if (preferences.expertMode) { return this.expertPrompt(config); } else { return this.guidedPrompt(config); } } async expertPrompt(_config) { // Minimal, streamlined prompt for expert users // Implementation would use minimal UI elements return null; } async guidedPrompt(_config) { // Rich, guided prompt with helpful hints // Implementation would use enhanced UI elements return null; } } // Contextual Validator export class ContextualValidator { validate(value, rules) { const errors = []; const warnings = []; const suggestions = []; for (const rule of rules) { const result = rule.validate(value); if (!result.valid) { if (result.severity === 'error') { errors.push(result.message); } else if (result.severity === 'warning') { warnings.push(result.message); } if (result.suggestion) { suggestions.push(result.suggestion); } } } return { valid: errors.length === 0, errors, warnings, suggestions }; } } // Real-time Feedback System export class RealTimeFeedback { icons = { success: chalk.green('✓'), error: chalk.red('✖'), warning: chalk.yellow('⚠'), info: chalk.cyan('ℹ'), loading: chalk.blue('◐') }; show(message, type) { const icon = this.icons[type]; const colorFn = this.getColorFunction(type); console.log(`${icon} ${colorFn(message)}`); } getColorFunction(type) { switch (type) { case 'success': return chalk.green; case 'error': return chalk.red; case 'warning': return chalk.yellow; case 'info': return chalk.cyan; default: return chalk.white; } } } // Inline Help Provider export class InlineHelpProvider { stateManager; constructor(stateManager) { this.stateManager = stateManager; } getHelp() { const currentState = this.stateManager.getCurrentNavigation(); const context = this.stateManager.getUserContext(); // Return contextual help based on current state return this.generateHelpText(currentState, context); } generateHelpText(state, _context) { if (!state) { return 'Type "help" for available commands'; } // Generate context-specific help const helps = { 'home': 'Main dashboard - choose an action or type a command', 'memory:create': 'Creating a new memory - provide title and content', 'memory:search': 'Search memories - use natural language or keywords', 'settings': 'Configure your preferences and authentication' }; return helps[state.name] || 'Type "?" for help, "←" to go back'; } } // Presentation Layer export class PresentationLayer { themeEngine; layoutManager; animationController; constructor() { this.themeEngine = new AdaptiveThemeEngine(); this.layoutManager = new ResponsiveLayoutManager(); this.animationController = new SubtleAnimationController(); } applyTheme(theme) { this.themeEngine.setTheme(theme); } renderLayout(content, layout) { this.layoutManager.render(content, layout); } animate(_element, _animation) { this.animationController.animate(_element, _animation); } } // Theme Engine export class AdaptiveThemeEngine { currentTheme = 'default'; themes = { default: { primary: chalk.blue.bold, secondary: chalk.gray, success: chalk.green, warning: chalk.yellow, error: chalk.red, info: chalk.cyan, accent: chalk.magenta, muted: chalk.dim, highlight: chalk.white.bold }, dark: { primary: chalk.cyanBright.bold, secondary: chalk.gray, success: chalk.greenBright, warning: chalk.yellowBright, error: chalk.redBright, info: chalk.blueBright, accent: chalk.magentaBright, muted: chalk.dim, highlight: chalk.whiteBright.bold } }; setTheme(theme) { if (theme in this.themes) { this.currentTheme = theme; } } getColors() { return this.themes[this.currentTheme]; } } // Layout Manager export class ResponsiveLayoutManager { render(content, layout) { // Implement different layout strategies switch (layout) { case 'card': this.renderContent(content); break; case 'table': this.renderTitle(content); break; case 'dashboard': this.renderDashboard(content); break; default: console.log(content); } } renderContent(content) { // Render content in card layout console.log('╭─────────────────────────────────────────╮'); console.log(`│ ${content.title || ''}`.padEnd(42) + '│'); console.log('├─────────────────────────────────────────┤'); console.log(`│ ${content.body || ''}`.padEnd(42) + '│'); console.log('╰─────────────────────────────────────────╯'); } renderTitle(_content) { // Render content in table layout // Implementation here } renderDashboard(_content) { // Render dashboard layout // Implementation here } } // Animation Controller export class SubtleAnimationController { animate(_element, _animation) { // Implement subtle animations for CLI // This would handle progress bars, spinners, etc. } } // Factory to create the complete architecture export function createCLIArchitecture() { const stateManager = new StateManager(); const interactionEngine = new InteractionEngine(stateManager); const presentationLayer = new PresentationLayer(); return { stateManager, interactionEngine, presentationLayer }; }