UNPKG

sushil-gitmate

Version:

Professional Git workflow automation powered by AI. Streamline your development process with natural language commands and intelligent automation.

311 lines (261 loc) 9.33 kB
#!/usr/bin/env node import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { handleNlpCommand, handleRepoCommand, handleGitCommand, handleGenerateGitignore, handleGenerateCommitMessage, handleAuthLogout, handleSwitchAIProvider } from '../commands/commandHandler.js'; import logger from '../src/utils/logger.js'; import UI from '../src/utils/ui.js'; import { storeToken } from '../src/utils/tokenManager.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Set the working directory to the project root for global installations process.chdir(process.cwd()); const serviceName = 'CLI'; async function main() { try { const args = process.argv.slice(2); if (args.length === 0) { showHelp(); return; } const command = args[0]; switch (command) { case '--version': case '-v': await showVersion(); break; case '--help': case '-h': showHelp(); break; case 'init': await handleInit(); break; case 'config': await handleConfig(args.slice(1)); break; case 'auth': await handleAuth(args.slice(1)); break; case 'repo': await handleRepoCommand(args.slice(1)); break; case 'git': await handleGitCommand(args.slice(1)); break; case 'generate-commit-message': await handleGenerateCommitMessage(); break; case 'generate-gitignore': { const description = args.slice(1).join(' '); await handleGenerateGitignore(description); } break; case 'switch-ai-provider': { const provider = args[1]; if (!provider) { UI.error('Provider Required', 'Please specify an AI provider: openai or anthropic'); process.exitCode = 1; return; } await handleSwitchAIProvider(provider); } break; case 'logout': await handleAuthLogout(); break; default: // Treat as NLP command await handleNlpCommand(command + ' ' + args.slice(1).join(' ')); break; } } catch (error) { logger.error('CLI error:', { message: error.message, stack: error.stack, service: serviceName }); UI.error('Unexpected Error', error.message); process.exitCode = 1; } } async function showVersion() { const packageJson = JSON.parse( await import('fs/promises').then(fs => fs.readFile(join(__dirname, '..', 'package.json'), 'utf8')) ); console.log(`GitBot Assistant v${packageJson.version}`); } function showHelp() { console.log(` GitBot Assistant - Professional Git workflow automation powered by AI USAGE: gitmate <command> [options] gitmate "natural language command" COMMANDS: init Initialize GitBot Assistant configuration config [options] Manage configuration settings auth <provider> Authenticate with external services repo <subcommand> Manage GitHub repositories git <subcommand> Execute Git operations generate-commit-message Generate commit message from changes generate-gitignore Generate .gitignore file switch-ai-provider Switch between AI providers logout Clear stored authentication tokens NATURAL LANGUAGE COMMANDS: gitmate "push my changes to main" gitmate "create a new branch called feature-x" gitmate "commit with message 'fix bug'" gitmate "create merge request from feature to main" OPTIONS: -h, --help Show this help message -v, --version Show version information EXAMPLES: gitmate init gitmate config --show gitmate "push code please" gitmate repo create my-project --private For more information, visit: https://github.com/yourusername/gitbot-assistant `); } async function handleInit() { try { UI.section('GitBot Assistant Initialization', 'Setting up your configuration...'); // Check if config already exists const configPath = join(process.env.HOME || process.env.USERPROFILE, '.gitmate', 'config.json'); const fs = await import('fs/promises'); try { await fs.access(configPath); const overwrite = await UI.confirm('Configuration already exists. Overwrite?', false); if (!overwrite) { console.log('Initialization cancelled.'); return; } } catch (error) { // Config doesn't exist, continue } // Create config directory const configDir = join(process.env.HOME || process.env.USERPROFILE, '.gitmate'); await fs.mkdir(configDir, { recursive: true }); // Initialize configuration const inquirer = (await import('inquirer')).default; const answers = await inquirer.prompt([ { type: 'list', name: 'aiProvider', message: 'Select your preferred AI provider:', choices: [ { name: 'Mistral (Recommended)', value: 'mistral' }, { name: 'OpenAI (GPT-4)', value: 'openai' }, { name: 'Anthropic (Claude)', value: 'anthropic' } ], default: 'mistral' }, { type: 'password', name: 'apiKey', message: 'Enter your API key:', validate: input => input.trim() !== '' || 'API key is required' }, { type: 'confirm', name: 'setupGitHub', message: 'Would you like to set up GitHub authentication now?', default: true } ]); // Save configuration const config = { aiProvider: answers.aiProvider, apiKey: answers.apiKey, version: '1.0.0', createdAt: new Date().toISOString() }; await fs.writeFile(configPath, JSON.stringify(config, null, 2)); UI.success('Configuration Saved', 'GitBot Assistant has been initialized successfully!'); if (answers.setupGitHub) { console.log('\nTo complete GitHub setup, run: gitmate auth github'); } } catch (error) { logger.error('Initialization error:', { message: error.message, stack: error.stack, service: serviceName }); UI.error('Initialization Failed', error.message); process.exitCode = 1; } } async function handleConfig(args) { try { const configPath = join(process.env.HOME || process.env.USERPROFILE, '.gitmate', 'config.json'); const fs = await import('fs/promises'); if (args.length === 0 || args.includes('--show')) { try { const config = JSON.parse(await fs.readFile(configPath, 'utf8')); console.log('\nCurrent Configuration:'); console.log(JSON.stringify(config, null, 2)); } catch (error) { UI.error('Configuration Not Found', 'Run "gitmate init" to create configuration.'); process.exitCode = 1; } return; } if (args.includes('--reset')) { const confirm = await UI.confirm('Are you sure you want to reset your configuration?', false); if (confirm) { await fs.unlink(configPath); UI.success('Configuration Reset', 'Configuration has been reset. Run "gitmate init" to reconfigure.'); } return; } // Handle other config options UI.warning('Unknown Config Option', `Unknown config option: ${args.join(' ')}`); console.log('Available options: --show, --reset'); } catch (error) { logger.error('Config error:', { message: error.message, stack: error.stack, service: serviceName }); UI.error('Configuration Error', error.message); process.exitCode = 1; } } async function handleAuth(args) { if (args.length === 0) { UI.error('Provider Required', 'Please specify an authentication provider (e.g., github)'); process.exitCode = 1; return; } const provider = args[0]; switch (provider.toLowerCase()) { case 'github': { // Start the auth server const { startAuthServer } = await import('../src/server/authServer.js'); await startAuthServer(); // Prompt for token after browser is opened const inquirer = (await import('inquirer')).default; const { token } = await inquirer.prompt([ { type: 'password', name: 'token', message: 'Paste the token you received from the browser:', mask: '*', validate: input => input.trim() !== '' || 'Token is required', }, ]); console.log("i am clalle"); await storeToken('github_access_token', token.trim()); console.log('Authentication Complete: Your GitHub token has been saved. You are now authenticated!'); break; } default: UI.error('Unknown Provider', `Unknown authentication provider: ${provider}`); process.exitCode = 1; break; } } // Handle process termination gracefully process.on('SIGINT', () => { console.log('\n\nGoodbye! 👋'); process.exit(0); }); process.on('SIGTERM', () => { console.log('\n\nGoodbye! 👋'); process.exit(0); }); // Run the CLI main().catch(error => { logger.error('Unhandled CLI error:', { message: error.message, stack: error.stack, service: serviceName }); UI.error('Fatal Error', error.message); process.exit(1); });