import * as fs from 'fs'; import * as path from 'path'; import inquirer from 'inquirer'; import { Command } from 'commander'; import { AppConfig, DEFAULT_CONFIG } from "../types/AppConfig"; export class CommandLineParser { public parse(): AppConfig { const program = new Command(); program .name('context-worker') .description('AutoDev Context Worker - Code analysis and context building tool') .version('1.0.0'); program .option('-p, --path ', 'Directory path to scan', DEFAULT_CONFIG.dirPath) .option('-u, --upload', 'Upload analysis results to server', DEFAULT_CONFIG.upload) .option('--server-url ', 'Server URL for uploading results', DEFAULT_CONFIG.baseUrl) .option('-o, --output-dir ', 'Output directory for learning materials', DEFAULT_CONFIG.outputDir) .option('-n, --non-interactive', 'Run in non-interactive mode', DEFAULT_CONFIG.nonInteractive) .option('--output-file ', 'JSON output file name', DEFAULT_CONFIG.outputJsonFile) .option('--interface', 'Process interface context only', false) .option('--api', 'Process API context only', true) .option('--project-id ', 'Project ID for organization', DEFAULT_CONFIG.projectId) .option('--run-interface', 'Run interface analysis', true) .option('--run-api', 'Run API analysis', true) .option('--run-symbol', 'Run symbol analysis', true) .option('--skip-interface', 'Skip interface analysis', false) .option('--skip-api', 'Skip API analysis', false) .option('--skip-symbol', 'Skip symbol analysis', false); program.parse(process.argv); const options = program.opts(); let contextType: 'api' | 'interface' = 'api'; if (options.interface) { contextType = 'interface'; } let dirPath = options.path; if (!path.isAbsolute(dirPath)) { dirPath = path.resolve(process.cwd(), dirPath); } // 处理分析类型选项 const analysisTypes = { interface: options.runInterface && !options.skipInterface, api: options.runApi && !options.skipApi, symbol: options.runSymbol && !options.skipSymbol }; return { dirPath, upload: options.upload || DEFAULT_CONFIG.upload, baseUrl: options.serverUrl || DEFAULT_CONFIG.baseUrl, outputDir: options.outputDir || DEFAULT_CONFIG.outputDir, nonInteractive: options.nonInteractive || DEFAULT_CONFIG.nonInteractive, contextType, outputJsonFile: options.outputFile || DEFAULT_CONFIG.outputJsonFile, projectId: options.projectId || DEFAULT_CONFIG.projectId, analysisTypes }; } } export class UserInputHandler { public async getAppConfig(currentConfig: AppConfig): Promise { const answers = await inquirer.prompt([ { type: 'input', name: 'dirPath', message: '请输入要扫描的目录路径:', default: currentConfig.dirPath, validate: (input) => { const fullPath = path.isAbsolute(input) ? input : path.resolve(process.cwd(), input); if (fs.existsSync(fullPath)) { return true; } return '请输入有效的目录路径'; } }, { type: 'confirm', name: 'upload', message: '是否要上传分析结果到服务器?', default: currentConfig.upload }, { type: 'input', name: 'serverUrl', message: '请输入 baseUrl 服务器地址:', default: currentConfig.baseUrl, when: (answers) => answers.upload }, { type: 'input', name: 'outputDir', message: '请输入分析结果输出目录:', default: currentConfig.outputDir }, { type: 'input', name: 'outputJsonFile', message: '请输入JSON结果输出文件名:', default: currentConfig.outputJsonFile }, { type: 'input', name: 'projectId', message: '请输入项目 ID (可选):', default: currentConfig.projectId }, { type: 'checkbox', name: 'analysisTypes', message: '请选择要运行的分析类型:', choices: [ { name: '接口分析', value: 'interface', checked: currentConfig.analysisTypes.interface }, { name: 'API分析', value: 'api', checked: currentConfig.analysisTypes.api }, { name: '关键代码标识', value: 'symbol', checked: currentConfig.analysisTypes.symbol } ] } ]); const dirPath = path.isAbsolute(answers.dirPath) ? answers.dirPath : path.resolve(process.cwd(), answers.dirPath); // 转换用户选择的分析类型 const selectedTypes = answers.analysisTypes || []; const analysisTypes = { interface: selectedTypes.includes('interface'), api: selectedTypes.includes('api'), symbol: selectedTypes.includes('symbol') }; // 如果用户没有选择任何类型,启用所有类型 if (!selectedTypes.length) { analysisTypes.interface = true; analysisTypes.api = true; analysisTypes.symbol = true; } return { dirPath, upload: answers.upload, baseUrl: answers.upload ? answers.serverUrl : currentConfig.baseUrl, outputDir: answers.outputDir, contextType: currentConfig.contextType, nonInteractive: currentConfig.nonInteractive, outputJsonFile: answers.outputJsonFile, projectId: answers.projectId, analysisTypes }; } }