UNPKG

@meldscience/meld

Version:

pipeable one-shot prompt scripting toolkit

165 lines (145 loc) • 5.65 kB
#!/usr/bin/env -S node --no-warnings --no-deprecation import { Command } from 'commander'; import { setupConfig, loadConfig, RC_FILE } from '../src/config'; import { homedir } from 'os'; import { join } from 'path'; import { existsSync } from 'fs'; import { createInterface } from 'readline'; async function interactiveSetup() { const rl = createInterface({ input: process.stdin, output: process.stdout }); const question = (query: string): Promise<string> => { return new Promise((resolve) => { rl.question(query, resolve); }); }; try { console.log('\nšŸ”§ Welcome to Meld Configuration Setup!\n'); // Ask about default models console.log('Which model would you like as your default?\n'); console.log(' • claude-3-opus-latest'); console.log(' • claude-3-5-sonnet-latest'); console.log(' • claude-3-5-haiku-latest'); console.log(' • chatgpt-4o-latest'); console.log(' • gpt-4o-mini'); console.log(' • chatgpt-4o1-latest'); console.log(' • gpt-4o1-mini\n'); const defaultOneshot = await question('oneshot default model [claude-3-5-sonnet-latest]: '); const defaultOneshotcat = await question('oneshotcat default model [claude-3-opus-latest]: '); // Ask about API keys console.log('\nNow, let\'s set up your API keys.'); const anthropicKey = await question('Anthropic API key (press Enter to skip): '); const openaiKey = await question('OpenAI API key (press Enter to skip): '); // Create config const config: any = { modelAliases: { 'claude': 'claude-3-5-sonnet-latest', 'sonnet': 'claude-3-5-sonnet-latest', 'opus': 'claude-3-opus-latest', 'haiku': 'claude-3-5-haiku-latest', '4o': 'chatgpt-4o-latest', '4o-mini': 'gpt-4o-mini', 'o1': 'chatgpt-4o1-latest', 'o1-mini': 'gpt-4o1-mini' }, defaultOneshotModel: defaultOneshot || 'claude-3-5-sonnet-latest', defaultOneshotcatModel: defaultOneshotcat || 'claude-3-opus-latest' }; if (anthropicKey) config.anthropicApiKey = anthropicKey; if (openaiKey) config.openaiApiKey = openaiKey; setupConfig(config); console.log('\nāœ… Configuration saved successfully!'); console.log(`\nYou can modify these settings anytime by editing ${join(homedir(), RC_FILE)}`); console.log('Or by running meld-config with the appropriate options (see meld-config --help)'); } finally { rl.close(); } } async function main() { const program = new Command(); program .name('meld-config') .description('Configure Meld settings and API keys') .option('--anthropic-key <key>', 'Set Anthropic API key') .option('--openai-key <key>', 'Set OpenAI API key') .option('--default-oneshot <model>', 'Set default model for oneshot command') .option('--default-oneshotcat <model>', 'Set default model for oneshotcat command') .option('--alias <alias=model>', 'Add or update a model alias', (value: string, previous: string[]) => { previous.push(value); return previous; }, []) .option('--init', 'Initialize config with default settings') .addHelpText('after', ` Examples: $ meld-config Run interactive setup $ meld-config --anthropic-key <key> Set Anthropic API key $ meld-config --openai-key <key> Set OpenAI API key $ meld-config --default-oneshot claude-3 Set default oneshot model $ meld-config --default-oneshotcat opus Set default oneshotcat model $ meld-config --alias "gpt4=gpt-4" Add model alias $ meld-config --init Reset to default settings For more examples and documentation: https://github.com/meldscience/oneshot#readme`); program.parse(process.argv); const options = program.opts(); // If no arguments provided and no config exists, run interactive setup const rcPath = join(homedir(), RC_FILE); if (process.argv.length === 2 && !existsSync(rcPath)) { await interactiveSetup(); return; } // Handle non-interactive options if (options.init) { setupConfig({ modelAliases: { 'claude': 'claude-3-5-sonnet-latest', 'sonnet': 'claude-3-5-sonnet-latest', 'opus': 'claude-3-opus-latest', 'haiku': 'claude-3-5-haiku-latest', '4o': 'chatgpt-4o-latest', '4o-mini': 'gpt-4o-mini', 'o1': 'chatgpt-4o1-latest', 'o1-mini': 'gpt-4o1-mini' }, defaultOneshotModel: 'claude-3-5-sonnet-latest', defaultOneshotcatModel: 'claude-3-opus-latest' }); console.log('āœ… Initialized default configuration'); return; } const config: any = {}; if (options.anthropicKey) { config.anthropicApiKey = options.anthropicKey; } if (options.openaiKey) { config.openaiApiKey = options.openaiKey; } if (options.defaultOneshot) { config.defaultOneshotModel = options.defaultOneshot; } if (options.defaultOneshotcat) { config.defaultOneshotcatModel = options.defaultOneshotcat; } if (options.alias && options.alias.length > 0) { const aliases: { [key: string]: string } = {}; for (const aliasStr of options.alias) { const [alias, model] = aliasStr.split('='); if (!alias || !model) { console.error('āŒ Invalid alias format. Use: alias=model'); process.exit(1); } aliases[alias] = model; } config.modelAliases = aliases; } if (Object.keys(config).length > 0) { setupConfig(config); console.log('āœ… Configuration updated'); } } main().catch(error => { console.error('āŒ Error:', error.message); process.exit(1); });