UNPKG

ctx-gen

Version:

AI-Enhanced Documentation Generator for Code Understanding

162 lines (157 loc) 6.68 kB
import { OpenAI } from 'openai'; import chalk from 'chalk'; // Create a shared OpenAI client instance let openaiClient = null; /** * Get or create an OpenAI client * @param apiKey - OpenAI API key * @returns OpenAI client instance */ function getOpenAIClient(apiKey) { if (!openaiClient) { openaiClient = new OpenAI({ apiKey: apiKey || process.env.OPENAI_API_KEY, }); } return openaiClient; } /** * Analyzes multiple files concurrently using OpenAI to enhance documentation * @param filesToAnalyze - Array of files to analyze * @param options - CtxGen options * @returns Map of file paths to enhanced documentation */ export async function analyzeFilesWithAI(filesToAnalyze, options) { // Get the maximum number of concurrent analyses const concurrentLimit = options.concurrentAiAnalyses || 3; const results = new Map(); // Process files in batches to respect the concurrent limit for (let i = 0; i < filesToAnalyze.length; i += concurrentLimit) { const batch = filesToAnalyze.slice(i, i + concurrentLimit); const batchSize = batch.length; const totalBatches = Math.ceil(filesToAnalyze.length / concurrentLimit); const currentBatch = Math.floor(i / concurrentLimit) + 1; // Show detailed batch progress const batchInfo = `Batch ${currentBatch}/${totalBatches}`; const filesInfo = `Processing ${batchSize} file${batchSize > 1 ? 's' : ''}`; const progressInfo = `(${i + 1}-${Math.min(i + batchSize, filesToAnalyze.length)} of ${filesToAnalyze.length})`; console.log(chalk.cyan(`🤖 ${batchInfo}: ${filesInfo} ${progressInfo}`)); // Initialize an array to track file progress const fileStatus = batch.map(file => { const shortName = file.filePath.split('/').pop() || file.filePath; return ` ⏳ ${shortName.padEnd(40, ' ')} - ${chalk.yellow('Processing...')}`; }); // Display initial status fileStatus.forEach(status => console.log(status)); // Process batch concurrently const batchPromises = batch.map((file, _index) => analyzeFileWithAI(file.filePath, file.content, file.language, file.basicDocumentation, options) .then(result => { results.set(file.filePath, result); // Update and display the updated status const shortName = file.filePath.split('/').pop() || file.filePath; console.log(` ✅ ${shortName.padEnd(40, ' ')} - ${chalk.green('Complete')}`); return true; }) .catch(error => { console.error(` ❌ Error analyzing ${file.filePath}:`, error); results.set(file.filePath, file.basicDocumentation); return false; })); // Wait for all files in this batch to complete await Promise.all(batchPromises); console.log(chalk.cyan(`✅ Batch ${currentBatch}/${totalBatches} complete\n`)); } return results; } /** * Analyzes a file using OpenAI to enhance documentation * @param filePath - The file path * @param content - The file content * @param language - The file language * @param basicDocumentation - The basic documentation to enhance * @param options - CtxGen options * @returns Enhanced documentation string */ export async function analyzeFileWithAI(filePath, content, language, basicDocumentation, options) { // Get OpenAI client const openai = getOpenAIClient(options.openaiKey); // Prepare the prompt for OpenAI const prompt = generateAIPrompt(filePath, content, language); try { // Make OpenAI API call const response = await openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [ { role: 'system', content: 'You are an expert code analyst specializing in generating documentation. Analyze the provided code and generate detailed, insightful documentation that would help an AI system understand the code better.', }, { role: 'user', content: prompt, }, ], temperature: 0.3, max_tokens: 2000, }); // Extract AI-generated documentation const aiAnalysis = response.choices[0]?.message.content || ''; // Enhance the basic documentation with AI insights return enhanceDocumentation(basicDocumentation, aiAnalysis, filePath); } catch (error) { console.error('Error calling OpenAI API:', error); // Return the basic documentation if AI analysis fails return basicDocumentation; } } /** * Generates a prompt for the AI model * @param filePath - The file path * @param content - The file content * @param language - The file language * @returns Prompt string for the AI model */ function generateAIPrompt(filePath, content, language) { return ` Please analyze the following ${language} code and provide detailed documentation: File: ${filePath} \`\`\`${language} ${content} \`\`\` Please provide the following information in markdown format: 1. A detailed summary of what this file/module does and its purpose 2. Functions/methods with their: - Purpose and behavior - Parameters (name, type, purpose) - Return values and side effects 3. Classes/objects with their: - Purpose and behavior - Properties and methods - Relationships with other classes/objects 4. Dependencies and imports with explanation of how they're used 5. Exports and their purpose 6. Key logic flows and algorithms described conceptually 7. Any patterns or architectural principles used 8. Potential edge cases or limitations Focus on providing insights that would help an AI understand the code's purpose, structure, and behavior. `; } /** * Enhances the basic documentation with AI-generated analysis * @param basicDocumentation - The basic documentation * @param aiAnalysis - The AI-generated analysis * @param filePath - The file path * @returns Enhanced documentation string */ function enhanceDocumentation(basicDocumentation, aiAnalysis, _filePath) { // Remove the source code section from the basic documentation // as it can be very long and the AI already analyzed it const sourceCodeStart = basicDocumentation.indexOf('## Source Code'); if (sourceCodeStart !== -1) { basicDocumentation = basicDocumentation.substring(0, sourceCodeStart); } // Combine the basic documentation with the AI analysis return `${basicDocumentation}\n\n${aiAnalysis}\n`; } //# sourceMappingURL=aiAnalyzer.js.map