UNPKG

codecrucible-synth

Version:

Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability

388 lines (353 loc) 10.5 kB
/** * CLI Argument Parser * Handles parsing of command line arguments and options */ import { CLIOptions } from './cli-types.js'; export class CLIParser { /** * Parse slash commands for role switching */ static parseSlashCommand(input: string): { command: string; role?: string; content: string } { const slashCommandRegex = /^\/(\w+)(?:\s+(.*))?$/; const match = input.match(slashCommandRegex); if (match) { const command = match[1]; const content = match[2] || ''; switch (command) { case 'auditor': return { command: 'role-switch', role: 'auditor', content }; case 'writer': return { command: 'role-switch', role: 'writer', content }; case 'auto': return { command: 'role-switch', role: 'auto', content }; case 'help': return { command: 'slash-help', content }; default: return { command: 'unknown-slash', content: input }; } } return { command: 'none', content: input }; } /** * Parse command line arguments into structured options */ static parseOptions(args: string[]): CLIOptions { const options: CLIOptions = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--')) { const key = arg.slice(2); const nextArg = args[i + 1]; switch (key) { case 'voices': if (nextArg && !nextArg.startsWith('--')) { options.voices = nextArg.split(',').map(v => v.trim()); i++; } break; case 'mode': if (nextArg && !nextArg.startsWith('--')) { options.mode = nextArg as any; i++; } break; case 'depth': if (nextArg && !nextArg.startsWith('--')) { options.depth = nextArg; i++; } break; case 'timeout': if (nextArg && !nextArg.startsWith('--')) { options.timeout = parseInt(nextArg, 10); i++; } break; case 'spiral-iterations': if (nextArg && !nextArg.startsWith('--')) { options.spiralIterations = parseInt(nextArg, 10); i++; } break; case 'spiral-quality': if (nextArg && !nextArg.startsWith('--')) { options.spiralQuality = parseFloat(nextArg); i++; } break; case 'max-steps': if (nextArg && !nextArg.startsWith('--')) { options.maxSteps = parseInt(nextArg, 10); i++; } break; case 'output': if (nextArg && !nextArg.startsWith('--')) { options.output = nextArg as 'text' | 'json' | 'table'; i++; } break; case 'backend': if (nextArg && !nextArg.startsWith('--')) { options.backend = nextArg as any; i++; } break; case 'port': if (nextArg && !nextArg.startsWith('--')) { options.port = nextArg; i++; } break; case 'writer-model': if (nextArg && !nextArg.startsWith('--')) { options.writerModel = nextArg; i++; } break; case 'auditor-model': if (nextArg && !nextArg.startsWith('--')) { options.auditorModel = nextArg; i++; } break; // Sequential Review options case 'writer-provider': if (nextArg && !nextArg.startsWith('--')) { options.writerProvider = nextArg as 'ollama' | 'lm-studio'; i++; } break; case 'auditor-provider': if (nextArg && !nextArg.startsWith('--')) { options.auditorProvider = nextArg as 'ollama' | 'lm-studio'; i++; } break; case 'writer-temp': if (nextArg && !nextArg.startsWith('--')) { options.writerTemp = parseFloat(nextArg); i++; } break; case 'auditor-temp': if (nextArg && !nextArg.startsWith('--')) { options.auditorTemp = parseFloat(nextArg); i++; } break; case 'writer-tokens': if (nextArg && !nextArg.startsWith('--')) { options.writerTokens = parseInt(nextArg, 10); i++; } break; case 'auditor-tokens': if (nextArg && !nextArg.startsWith('--')) { options.auditorTokens = parseInt(nextArg, 10); i++; } break; case 'confidence-threshold': if (nextArg && !nextArg.startsWith('--')) { options.confidenceThreshold = parseFloat(nextArg); i++; } break; // Boolean flags case 'interactive': options.interactive = true; break; case 'spiral': options.spiral = true; break; case 'autonomous': options.autonomous = true; break; case 'council': options.council = true; break; case 'agentic': options.agentic = true; break; case 'quick': options.quick = true; break; case 'direct': options.direct = true; break; case 'verbose': options.verbose = true; break; case 'quiet': options.quiet = true; break; case 'fast': options.fast = true; break; case 'skip-init': options.skipInit = true; break; case 'iterative': options.iterative = true; break; case 'stream': options.stream = true; break; case 'no-stream': options.noStream = true; break; case 'enable-intelligence': options.enableIntelligence = true; break; case 'context-aware': options.contextAware = true; break; case 'smart-suggestions': options.smartSuggestions = true; break; case 'project-analysis': options.projectAnalysis = true; break; case 'dual-agent': options.dualAgent = true; break; case 'realtime-audit': options.realtimeAudit = true; break; case 'auto-fix': options.autoFix = true; break; case 'stream-generation': options.streamGeneration = true; break; // Sequential Review boolean flags case 'sequential-review': options.sequentialReview = true; break; case 'auto-audit': options.autoAudit = true; break; case 'apply-fixes': options.applyFixes = true; break; case 'save-result': options.saveResult = true; break; case 'show-code': options.showCode = true; break; case 'status': options.status = true; break; case 'optimize': options.optimize = true; break; case 'test': options.test = true; break; case 'models': options.models = true; break; case 'configure': options.configure = true; break; case 'server': options.server = true; break; case 'project': options.project = true; break; } } else if (arg.startsWith('-') && arg.length === 2) { // Short flags const flag = arg[1]; switch (flag) { case 'v': options.verbose = true; break; case 'q': options.quiet = true; break; case 'i': options.interactive = true; break; case 'f': options.fast = true; break; case 's': options.spiral = true; break; case 'a': options.autonomous = true; break; } } } return options; } /** * Extract the main command from arguments */ static extractCommand(args: string[]): { command: string; remainingArgs: string[] } { const commands = ['analyze', 'generate', 'status', 'models', 'configure', 'help']; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (commands.includes(arg)) { return { command: arg, remainingArgs: args.slice(i + 1), }; } } return { command: '', remainingArgs: args, }; } /** * Check if arguments contain help flags */ static isHelpRequest(args: string[]): boolean { return args.includes('--help') || args.includes('-h') || args.includes('help'); } /** * Get non-option arguments (potential prompts or files) */ static getNonOptionArgs(args: string[]): string[] { const nonOptions: string[] = []; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('-')) { // Skip this option and its value if it has one const nextArg = args[i + 1]; if (nextArg && !nextArg.startsWith('-') && this.isOptionWithValue(arg)) { i++; // Skip the value } } else { nonOptions.push(arg); } } return nonOptions; } /** * Check if an option expects a value */ private static isOptionWithValue(option: string): boolean { const optionsWithValues = [ '--voices', '--mode', '--depth', '--timeout', '--spiral-iterations', '--spiral-quality', '--max-steps', '--output', '--backend', '--port', '--writer-model', '--auditor-model', ]; return optionsWithValues.includes(option); } }