UNPKG

ai-expert

Version:

AI Expert CLI - Advanced management system for specialized Claude assistants

217 lines • 9.03 kB
import { Command } from 'commander'; import { ExpertBuilder } from '../../services/expert-builder.js'; import inquirer from 'inquirer'; import chalk from 'chalk'; export function expertCommand(storage) { const expert = new Command('expert'); const builder = new ExpertBuilder(storage); expert .description('Manage AI experts') .alias('e'); expert .command('create <name>') .description('Create a new expert') .option('-d, --description <desc>', 'Expert description') .option('-c, --context <id>', 'Base context ID') .option('-s, --system <id>', 'Base system ID (overrides context system)') .option('--category <category>', 'Expert category') .option('-t, --tags <tags...>', 'Expert tags') .action(async (name, options) => { try { // Interactive mode if no options provided if (!options.description || !options.context) { const contexts = await storage.listContexts(); const systems = await storage.listSystems(); const config = await storage.getConfig(); const answers = await inquirer.prompt([ { type: 'input', name: 'description', message: 'Expert description:', default: options.description, when: !options.description }, { type: 'list', name: 'context', message: 'Select base context:', choices: [ { name: 'None', value: null }, ...contexts.map(c => ({ name: `${c.name} - ${c.description}`, value: c.id })) ], when: !options.context }, { type: 'list', name: 'system', message: 'Select base system (optional):', choices: [ { name: 'Use context default', value: null }, ...systems.map(s => ({ name: `${s.name} - ${s.description}`, value: s.id })) ], when: !options.system }, { type: 'list', name: 'category', message: 'Select category:', choices: config.categories.experts, default: options.category || 'custom' } ]); Object.assign(options, answers); } const expert = await builder.createExpert(name, options.description, { baseContextId: options.context, baseSystemId: options.system, category: options.category, tags: options.tags }); console.log(chalk.green('āœ… Expert created successfully!')); console.log(chalk.cyan(`ID: ${expert.id}`)); console.log(chalk.cyan(`Slug: ${expert.slug}`)); console.log(`\nUse: ${chalk.yellow(`ai ${expert.slug} "your question"`)}`); } catch (error) { console.error(chalk.red('āŒ Error:'), error.message); } }); expert .command('list') .description('List all experts') .option('-c, --category <category>', 'Filter by category') .option('--json', 'Output as JSON') .action(async (options) => { try { const experts = await storage.listExperts(options.category); if (options.json) { console.log(JSON.stringify(experts, null, 2)); return; } if (experts.length === 0) { console.log(chalk.yellow('No experts found.')); console.log(`Create one with: ${chalk.cyan('ai expert create <name>')}`); return; } console.log(chalk.bold('\nšŸ¤– Available Experts:\n')); for (const expert of experts) { console.log(chalk.cyan(`šŸ“Œ ${expert.slug}`) + chalk.gray(` - ${expert.name}`)); console.log(` ${expert.description}`); if (expert.category) { console.log(chalk.gray(` Category: ${expert.category}`)); } if (expert.tags?.length) { console.log(chalk.gray(` Tags: ${expert.tags.join(', ')}`)); } if (expert.usageCount > 0) { console.log(chalk.gray(` Used: ${expert.usageCount} times`)); } console.log(); } } catch (error) { console.error(chalk.red('āŒ Error:'), error.message); } }); expert .command('show <slug>') .description('Show expert details') .option('--json', 'Output as JSON') .action(async (slug, options) => { try { const expert = await storage.getExpert(slug); if (!expert) { console.error(chalk.red(`āŒ Expert '${slug}' not found`)); return; } if (options.json) { console.log(JSON.stringify(expert, null, 2)); return; } console.log(chalk.bold(`\nšŸ¤– Expert: ${expert.name}\n`)); console.log(`Slug: ${chalk.cyan(expert.slug)}`); console.log(`Description: ${expert.description}`); console.log(`Category: ${expert.category}`); if (expert.tags?.length) { console.log(`Tags: ${expert.tags.join(', ')}`); } if (expert.baseContextId) { const context = await storage.getContext(expert.baseContextId); console.log(`Base Context: ${chalk.cyan(context?.name || expert.baseContextId)}`); } if (expert.baseSystemId) { const system = await storage.getSystem(expert.baseSystemId); console.log(`Base System: ${chalk.cyan(system?.name || expert.baseSystemId)}`); } console.log(`Created: ${new Date(expert.created).toLocaleString()}`); if (expert.updated) { console.log(`Updated: ${new Date(expert.updated).toLocaleString()}`); } console.log(`Usage: ${expert.usageCount} times`); if (expert.additionalRules.length > 0) { console.log(chalk.bold('\nAdditional Rules:')); for (const rule of expert.additionalRules) { console.log(`- ${rule.name}: ${rule.content}`); } } } catch (error) { console.error(chalk.red('āŒ Error:'), error.message); } }); expert .command('edit <slug>') .description('Edit expert configuration') .action(async (slug) => { try { const expert = await storage.getExpert(slug); if (!expert) { console.error(chalk.red(`āŒ Expert '${slug}' not found`)); return; } // Open editor const { edit } = await import('../../utils/editor.js'); const updated = await edit(expert); if (updated) { updated.updated = new Date().toISOString(); await storage.saveExpert(updated); console.log(chalk.green('āœ… Expert updated successfully!')); } } catch (error) { console.error(chalk.red('āŒ Error:'), error.message); } }); expert .command('delete <slug>') .description('Delete an expert') .option('-f, --force', 'Skip confirmation') .action(async (slug, options) => { try { const expert = await storage.getExpert(slug); if (!expert) { console.error(chalk.red(`āŒ Expert '${slug}' not found`)); return; } if (!options.force) { const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: `Are you sure you want to delete expert '${expert.name}'?`, default: false }]); if (!confirm) { console.log('Cancelled.'); return; } } await storage.deleteExpert(slug); console.log(chalk.green(`āœ… Expert '${expert.name}' deleted successfully!`)); } catch (error) { console.error(chalk.red('āŒ Error:'), error.message); } }); return expert; } //# sourceMappingURL=expert.js.map