UNPKG

flash-tool-oss

Version:

Fast AI-powered code completion using OpenAI API - No API key setup required!

273 lines (225 loc) • 9.04 kB
#!/usr/bin/env node const { Command } = require('commander'); const { spawn } = require('child_process'); const path = require('path'); const readline = require('readline'); const fs = require('fs'); const program = new Command(); function callPythonScript(scriptPath, args) { return new Promise((resolve, reject) => { const pythonProcess = spawn('python', [scriptPath, ...args]); let output = ''; let errorOutput = ''; pythonProcess.stdout.on('data', (data) => { output += data.toString(); }); pythonProcess.stderr.on('data', (data) => { errorOutput += data.toString(); }); pythonProcess.on('close', (code) => { if (code === 0) { resolve(output.trim()); } else { reject(new Error(`Python script failed: ${errorOutput}`)); } }); }); } function insertCodeIntoFile(filePath, insertAfter, codeToInsert) { const fileContent = fs.readFileSync(filePath, 'utf8'); const lines = fileContent.split('\n'); const insertIndex = lines.findIndex(line => line.includes(insertAfter)); if (insertIndex === -1) { throw new Error(`Could not find insertion point: "${insertAfter}"`); } lines.splice(insertIndex + 1, 0, codeToInsert); fs.writeFileSync(filePath, lines.join('\n'), 'utf8'); console.log(`āœ… Code inserted into ${filePath} after "${insertAfter}"`); } program .name('flash-tool-oss') .description('Fast AI-powered code completion using OpenAI API') .version('1.0.0'); // Complete command program .command('complete') .description('Complete code using AI') .argument('[context]', 'Code context to complete') .option('-l, --language <language>', 'Programming language', 'python') .option('-f, --file <filePath>', 'Target file to insert completion into') .action(async (context, options) => { try { if (!context) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); context = await new Promise((resolve) => { rl.question('Enter the code context to complete: ', (answer) => { rl.close(); resolve(answer.trim()); }); }); if (!context) { console.error('āŒ Error: Context cannot be empty'); return; } } let fileContent = ''; if (options.file) { if (!fs.existsSync(options.file)) { console.error(`āŒ File not found: ${options.file}`); return; } fileContent = fs.readFileSync(options.file, 'utf8'); } console.log('šŸ¤– Generating code completion...'); const scriptPath = path.join(__dirname, 'extension.py'); const rawOutput = await callPythonScript(scriptPath, [ 'complete', context, options.language, fileContent ]); let completionObject; try { completionObject = JSON.parse(rawOutput); } catch { console.error('āŒ Error: Could not parse response from Python script. Expected JSON.'); console.log('Raw output:', rawOutput); return; } const { insert_after, code } = completionObject; if (!code || !insert_after) { console.error('āŒ Error: Incomplete response. Must include both "insert_after" and "code".'); return; } console.log('\n✨ Code to insert:\n' + code); if (options.file) { insertCodeIntoFile(options.file, insert_after, code); } else { console.log('\nšŸ“ No file specified. Code not inserted.'); } } catch (error) { console.error('āŒ Error:', error.message); } }); // Chat command program .command('chat') .description('Chat with AI assistant') .argument('[message]', 'Message to send to AI') .action(async (message) => { try { if (!message) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); message = await new Promise((resolve) => { rl.question('What would you like to ask? ', (answer) => { rl.close(); resolve(answer.trim()); }); }); if (!message) { console.error('āŒ Error: Message cannot be empty'); return; } } console.log('šŸ¤– Thinking...'); const scriptPath = path.join(__dirname, 'extension.py'); const response = await callPythonScript(scriptPath, ['chat', message]); console.log('\nšŸ’¬ AI Response:'); console.log(response); } catch (error) { console.error('āŒ Error:', error.message); } }); // Interactive mode program .command('interactive') .alias('i') .description('Start interactive mode') .action(async () => { console.log('šŸš€ Flash Interactive Mode'); console.log('Type "exit" to quit\n'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const askQuestion = (question) => { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer.trim()); }); }); }; while (true) { console.log('Options:'); console.log('1. šŸ’¬ Chat with AI'); console.log('2. ✨ Complete code'); console.log('3. 🚪 Exit'); const choice = await askQuestion('\nWhat would you like to do? (1-3): '); if (choice === '3' || choice.toLowerCase() === 'exit') { console.log('šŸ‘‹ Goodbye!'); rl.close(); break; } if (choice === '1') { const message = await askQuestion('What would you like to ask? '); if (message) { try { console.log('šŸ¤– Thinking...'); const scriptPath = path.join(__dirname, 'extension.py'); const response = await callPythonScript(scriptPath, ['chat', message]); console.log('\nšŸ’¬ AI Response:'); console.log(response); console.log(); // Empty line for spacing } catch (error) { console.error('āŒ Error:', error.message); } } } if (choice === '2') { const context = await askQuestion('Enter the code context to complete: '); const filePath = await askQuestion('Path to target file (optional): '); const language = await askQuestion('Programming language (default: python): ') || 'python'; let fileContent = ''; if (filePath) { try { fileContent = fs.readFileSync(filePath, 'utf8'); } catch (err) { console.error(`āŒ Failed to read file: ${err.message}`); continue; } } try { console.log('šŸ¤– Generating code completion...'); const scriptPath = path.join(__dirname, 'extension.py'); const rawOutput = await callPythonScript(scriptPath, [ 'complete', context, language, fileContent ]); let completionObject = JSON.parse(rawOutput); const { insert_after, code } = completionObject; console.log('\n✨ Code to insert:\n' + code); if (filePath) { insertCodeIntoFile(filePath, insert_after, code); } else { console.log('\nšŸ“ No file specified. Code not inserted.'); } console.log(); // spacing } catch (error) { console.error('āŒ Error:', error.message); } } } }); // Default command (show help) program.action(() => { program.help(); }); program.parse();