khodkar-cli
Version:
A TypeScript CLI application that extracts business rules and logic from codebases for customer support knowledge bases
137 lines • 6.32 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KhodkarCLI = void 0;
const commander_1 = require("commander");
const chalk_1 = __importDefault(require("chalk"));
const types_1 = require("../types");
const llm_processor_1 = require("../analysis/llm-processor");
const progress_tracker_1 = require("../utils/progress-tracker");
const package_json_1 = require("../../package.json");
const manager_1 = require("../mcp/manager");
const fs_1 = require("fs");
class KhodkarCLI {
program;
mcpManager;
constructor() {
this.program = new commander_1.Command();
this.mcpManager = new manager_1.McpManager();
this.setupCommands();
}
setupCommands() {
this.program
.name('khodkar')
.description('Extract business rules and logic from codebases for customer support knowledge bases')
.version(package_json_1.version);
this.program
.command('analyze')
.description('Analyze a codebase and extract business rules')
.requiredOption('-d, --directory <path>', 'Target codebase directory to analyze')
.requiredOption('-o, --output <path>', 'Output file path for extracted business rules')
.requiredOption('--llm-base-url <url>', 'LLM API base URL (e.g., https://api.openai.com/v1, https://api.anthropic.com)')
.requiredOption('--llm-api-key <key>', 'LLM API key for authentication')
.requiredOption('--llm-model <model>', 'LLM model name (e.g., gpt-4, claude-3-sonnet-20240229)')
.option('-f, --format <format>', 'Output format (json|markdown)', 'markdown')
.option('-v, --verbose', 'Enable detailed progress logging', false)
.option('--llm-max-tokens <number>', 'Maximum tokens for LLM response (1000-32000)', parseInt)
.option('--llm-max-steps <number>', 'Maximum analysis steps for LLM (10-500)', parseInt)
.action(async (options) => {
await this.handleAnalyzeCommand(options);
});
}
async run(argv) {
// try {
await this.program.parseAsync(argv);
// } catch (error) {
// const message = error instanceof Error ? error.message : 'Unknown error';
// console.error(chalk.red(`Error: ${message}`));
// process.exit(1);
// }
}
async handleAnalyzeCommand(rawOptions) {
// Validate and parse options
const options = this.validateOptions(rawOptions);
// // Create and validate LLM configuration from CLI options
const llmConfig = {
baseUrl: options.llmBaseUrl,
apiKey: options.llmApiKey,
model: options.llmModel,
maxSteps: options.llmMaxSteps || 50,
};
// Validate LLM configuration
try {
types_1.LLMConfigSchema.parse(llmConfig);
}
catch (error) {
const message = error instanceof Error ? error.message : 'Invalid LLM configuration';
throw new Error(`LLM Configuration Error: ${message}`);
}
// Initialize LLM processor with user configuration
const llmProcessor = new llm_processor_1.LLMProcessor(llmConfig);
const progressTracker = new progress_tracker_1.ProgressTracker({
verbose: options.verbose,
showETA: true,
});
// try {
progressTracker.start('Initializing analysis...');
if (options.verbose) {
console.log(chalk_1.default.blue('🔍 Starting business rules analysis...'));
console.log(chalk_1.default.gray(`Directory: ${options.directory}`));
console.log(chalk_1.default.gray(`Output: ${options.output}`));
console.log(chalk_1.default.gray(`Format: ${options.format}`));
}
// Initialize MCP servers
progressTracker.updatePhase('scanning', 'Initializing MCP servers...');
await this.mcpManager.initializeServers();
// Analyze files with LLM
progressTracker.updatePhase('analyzing', 'Analyzing codebase with LLM...');
const tools = await this.mcpManager.getTools();
const businessRules = await llmProcessor.analyze(tools);
(0, fs_1.writeFileSync)(options.output, businessRules, { encoding: 'utf-8' });
progressTracker.succeed('Analysis complete!');
console.log(chalk_1.default.green('✅ Analysis complete!'));
console.log(chalk_1.default.blue(`📄 Output saved to: ${options.output}`));
// Cleanup resources
await llmProcessor.cleanup();
await this.mcpManager.shutdownServers();
// } catch (error) {
// progressTracker.fail('Analysis failed');
// await this.handleError(error);
// // Cleanup resources even on error
// await llmProcessor.cleanup();
// await this.mcpManager.shutdownServers();
// }
}
validateOptions(rawOptions) {
try {
return types_1.CLIOptionsSchema.parse(rawOptions);
}
catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
throw new Error(`Invalid options: ${message}`);
}
}
async handleError(error) {
if (error instanceof types_1.LLMAnalysisError) {
console.error(chalk_1.default.red(`LLM analysis error: ${error.message}`));
if (error.details?.filePath) {
console.error(chalk_1.default.gray(`File: ${error.details.filePath}`));
}
}
else if (error instanceof types_1.MCPServerError) {
console.error(chalk_1.default.red(`MCP server error: ${error.message}`));
if (error.details?.serverName) {
console.error(chalk_1.default.gray(`Server: ${error.details.serverName}`));
}
}
else {
const message = error instanceof Error ? error.message : 'Unknown error';
console.error(chalk_1.default.red(`Unexpected error: ${message}`));
}
process.exit(1);
}
}
exports.KhodkarCLI = KhodkarCLI;
//# sourceMappingURL=commands.js.map