UNPKG

@chittyos/mcp

Version:

ChittyMCP - Model Context Protocol server for ChittyOS ecosystem

430 lines (386 loc) • 13.1 kB
#!/usr/bin/env node /** * Branched CLI - Direct terminal interface for branched operations */ import { Command } from 'commander'; import chalk from 'chalk'; import inquirer from 'inquirer'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); class BranchedCLI { constructor() { this.program = new Command(); this.branches = new Map(); this.config = this.loadConfig(); this.setupCLI(); this.loadBranches(); } loadConfig() { const configPath = path.join(__dirname, 'config.json'); if (fs.existsSync(configPath)) { return JSON.parse(fs.readFileSync(configPath, 'utf8')); } return { enabledBranches: ['finance', 'chat', 'code', 'data'], defaultBranch: 'finance', }; } loadBranches() { const branchesDir = path.join(__dirname, 'branches'); // Load CLI branches (different from MCP branches) this.branches.set('finance', { commands: { portfolio: async (args) => { console.log(chalk.blue('šŸ“Š Portfolio Status:')); console.log('AAPL: 50 shares @ $175 (+16.67%)'); console.log('MSFT: 30 shares @ $380 (+26.67%)'); console.log(chalk.green('Total Value: $20,150')); }, compound: async (args) => { const { principal, rate, years } = args; const amount = principal * Math.pow(1 + rate/100, years); console.log(chalk.yellow(`šŸ’° Compound Interest Calculator:`)); console.log(`Principal: $${principal}`); console.log(`Rate: ${rate}%`); console.log(`Time: ${years} years`); console.log(chalk.green(`Future Value: $${amount.toFixed(2)}`)); }, loan: async (args) => { const { amount, rate, months } = args; const r = rate / 100 / 12; const payment = amount * (r * Math.pow(1 + r, months)) / (Math.pow(1 + r, months) - 1); console.log(chalk.yellow(`šŸ  Loan Calculator:`)); console.log(`Amount: $${amount}`); console.log(`Rate: ${rate}%`); console.log(`Term: ${months} months`); console.log(chalk.green(`Monthly Payment: $${payment.toFixed(2)}`)); }, }, }); this.branches.set('chat', { commands: { gpt: async (args) => { const { message } = args; console.log(chalk.cyan('šŸ¤– GPT Response:')); console.log(`[Simulated] Response to: "${message}"`); }, claude: async (args) => { const { message } = args; console.log(chalk.magenta('šŸŽ­ Claude Response:')); console.log(`[Simulated] Response to: "${message}"`); }, compare: async (args) => { const { message } = args; console.log(chalk.blue('āš–ļø Comparing AI Responses:')); console.log(chalk.cyan('GPT: [Response would go here]')); console.log(chalk.magenta('Claude: [Response would go here]')); }, }, }); this.branches.set('code', { commands: { analyze: async (args) => { const { file } = args; console.log(chalk.green(`šŸ” Analyzing: ${file}`)); console.log('Lines: 150'); console.log('Functions: 12'); console.log('Complexity: Medium'); }, generate: async (args) => { const { type, name } = args; console.log(chalk.yellow(`⚔ Generating ${type}: ${name}`)); console.log('// Generated code would appear here'); }, refactor: async (args) => { const { file, goal } = args; console.log(chalk.blue(`šŸ”§ Refactoring ${file}`)); console.log(`Goal: ${goal || 'improve readability'}`); }, }, }); this.branches.set('data', { commands: { analyze: async (args) => { const { data, operation } = args; console.log(chalk.cyan(`šŸ“Š Data Analysis (${operation}):`)); console.log('Result: [Analysis would go here]'); }, transform: async (args) => { const { input, operation } = args; console.log(chalk.yellow(`šŸ”„ Transforming data: ${operation}`)); console.log('Output: [Transformed data]'); }, visualize: async (args) => { const { data, type } = args; console.log(chalk.green(`šŸ“ˆ Creating ${type} chart`)); console.log('[Visualization description]'); }, }, }); } setupCLI() { this.program .name('mcp') .description('Branched CLI for modular operations') .version('1.0.0'); // Main branch router this.program .command('branch <branch>') .description('Switch to a specific branch') .action((branch) => { if (this.branches.has(branch)) { console.log(chalk.green(`āœ“ Switched to ${branch} branch`)); this.config.defaultBranch = branch; } else { console.log(chalk.red(`āœ— Unknown branch: ${branch}`)); console.log(`Available: ${Array.from(this.branches.keys()).join(', ')}`); } }); // Finance branch const finance = this.program .command('finance') .alias('f') .description('Financial operations'); finance .command('portfolio') .alias('p') .description('Show portfolio status') .action(() => this.branches.get('finance').commands.portfolio()); finance .command('compound <principal> <rate> <years>') .alias('c') .description('Calculate compound interest') .action((principal, rate, years) => { this.branches.get('finance').commands.compound({ principal: parseFloat(principal), rate: parseFloat(rate), years: parseFloat(years), }); }); finance .command('loan <amount> <rate> <months>') .alias('l') .description('Calculate loan payment') .action((amount, rate, months) => { this.branches.get('finance').commands.loan({ amount: parseFloat(amount), rate: parseFloat(rate), months: parseInt(months), }); }); // Chat branch const chat = this.program .command('chat') .alias('c') .description('AI chat operations'); chat .command('gpt <message...>') .alias('g') .description('Chat with GPT') .action((message) => { this.branches.get('chat').commands.gpt({ message: message.join(' '), }); }); chat .command('claude <message...>') .alias('c') .description('Chat with Claude') .action((message) => { this.branches.get('chat').commands.claude({ message: message.join(' '), }); }); chat .command('compare <message...>') .alias('vs') .description('Compare AI responses') .action((message) => { this.branches.get('chat').commands.compare({ message: message.join(' '), }); }); // Code branch const code = this.program .command('code') .alias('c') .description('Code operations'); code .command('analyze <file>') .alias('a') .description('Analyze code file') .action((file) => { this.branches.get('code').commands.analyze({ file }); }); code .command('generate <type> <name>') .alias('g') .description('Generate code') .action((type, name) => { this.branches.get('code').commands.generate({ type, name }); }); code .command('refactor <file>') .alias('r') .description('Refactor code') .option('--goal <goal>', 'Refactoring goal') .action((file, options) => { this.branches.get('code').commands.refactor({ file, goal: options.goal, }); }); // Data branch const data = this.program .command('data') .alias('d') .description('Data operations'); data .command('analyze <operation>') .alias('a') .description('Analyze data') .option('--data <data>', 'Input data (JSON)') .action((operation, options) => { this.branches.get('data').commands.analyze({ operation, data: options.data ? JSON.parse(options.data) : [], }); }); data .command('transform <operation>') .alias('t') .description('Transform data') .option('--input <data>', 'Input data') .action((operation, options) => { this.branches.get('data').commands.transform({ operation, input: options.input, }); }); // Interactive mode this.program .command('interactive') .alias('i') .description('Interactive branch mode') .action(async () => { await this.interactiveMode(); }); // List all branches and commands this.program .command('list') .alias('ls') .description('List all branches and commands') .action(() => { console.log(chalk.bold('\n🌳 Available Branches:\n')); this.branches.forEach((branch, name) => { console.log(chalk.green(` ${name}:`)); Object.keys(branch.commands).forEach(cmd => { console.log(` - ${cmd}`); }); }); }); // Quick access with dynamic routing this.program .command('quick <branch>:<command> [args...]') .alias('q') .description('Quick command execution') .action(async (branchCommand, args) => { const [branch, command] = branchCommand.split(':'); if (this.branches.has(branch)) { const branchObj = this.branches.get(branch); if (branchObj.commands[command]) { await branchObj.commands[command](args); } else { console.log(chalk.red(`Command '${command}' not found in branch '${branch}'`)); } } else { console.log(chalk.red(`Branch '${branch}' not found`)); } }); } async interactiveMode() { console.log(chalk.bold.cyan('\nšŸŽÆ Interactive Branched CLI\n')); while (true) { const { action } = await inquirer.prompt([ { type: 'list', name: 'action', message: 'Choose a branch:', choices: [ ...Array.from(this.branches.keys()), new inquirer.Separator(), 'Exit', ], }, ]); if (action === 'Exit') break; const branch = this.branches.get(action); const { command } = await inquirer.prompt([ { type: 'list', name: 'command', message: `Choose a ${action} command:`, choices: Object.keys(branch.commands), }, ]); // Get command-specific inputs const inputs = await this.getCommandInputs(action, command); await branch.commands[command](inputs); console.log(''); // Add spacing } } async getCommandInputs(branch, command) { const inputConfigs = { finance: { compound: [ { type: 'number', name: 'principal', message: 'Principal amount:' }, { type: 'number', name: 'rate', message: 'Interest rate (%):' }, { type: 'number', name: 'years', message: 'Years:' }, ], loan: [ { type: 'number', name: 'amount', message: 'Loan amount:' }, { type: 'number', name: 'rate', message: 'Interest rate (%):' }, { type: 'number', name: 'months', message: 'Months:' }, ], }, chat: { gpt: [{ type: 'input', name: 'message', message: 'Your message:' }], claude: [{ type: 'input', name: 'message', message: 'Your message:' }], compare: [{ type: 'input', name: 'message', message: 'Your message:' }], }, code: { analyze: [{ type: 'input', name: 'file', message: 'File to analyze:' }], generate: [ { type: 'input', name: 'type', message: 'Type (function/class/component):' }, { type: 'input', name: 'name', message: 'Name:' }, ], refactor: [ { type: 'input', name: 'file', message: 'File to refactor:' }, { type: 'input', name: 'goal', message: 'Goal (optional):' }, ], }, data: { analyze: [ { type: 'list', name: 'operation', message: 'Operation:', choices: ['mean', 'median', 'summary'] }, { type: 'input', name: 'data', message: 'Data (JSON array):' }, ], transform: [ { type: 'list', name: 'operation', message: 'Transform:', choices: ['normalize', 'sort', 'filter'] }, { type: 'input', name: 'input', message: 'Input data:' }, ], }, }; const config = inputConfigs[branch]?.[command]; if (!config) return {}; return await inquirer.prompt(config); } run() { this.program.parse(); } } // Run the CLI const cli = new BranchedCLI(); cli.run();