UNPKG

@entro314labs/ai-changelog-generator

Version:

AI-powered changelog generator with MCP server support - works with most providers, online and local models

252 lines (251 loc) 8.79 kB
#!/usr/bin/env node import { ApplicationService } from './application/services/application.service.js'; import colors from './shared/constants/colors.js'; /** * AI Changelog Generator - Main Facade Class * * Provides the primary interface for changelog generation functionality * by delegating to domain services through the ApplicationService layer. * * Features: * - Automatic changelog generation from git commits * - Working directory change analysis * - Multiple AI provider support * - Interactive and batch modes */ export class AIChangelogGenerator { constructor(options = {}) { this.options = options; this.appService = new ApplicationService(options); // Simple configuration this.analysisMode = options.analysisMode || 'standard'; this.modelOverride = options.modelOverride || null; this.dryRun = options.dryRun; this.silent = options.silent; if (!this.silent) { console.log(colors.successMessage('🚀 AI Changelog Generator initialized')); } } // Main changelog generation - delegates to service layer. // `options` carries format/template/attribution/analysisMode/outputFile; without // it, embedders (the VS Code extension) had no way to reach those controls at all. async generateChangelog(version = null, since = null, options = {}) { try { if (this.dryRun && !this.silent) { console.log(colors.infoMessage('DRY RUN MODE - No files will be written')); } return await this.appService.generateChangelog({ analysisMode: this.analysisMode, ...options, version, since, ...(this.dryRun !== undefined ? { dryRun: this.dryRun } : {}), ...(this.silent !== undefined ? { silent: this.silent } : {}), }); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Changelog generation failed:'), error.message); } throw error; } } // Repository analysis - delegates to analysis engine async analyzeRepository(config = {}) { try { return await this.appService.analyzeRepository(config); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Repository analysis failed:'), error.message); } throw error; } } // Current changes analysis async analyzeCurrentChanges() { try { return await this.appService.analyzeCurrentChanges(); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Changes analysis failed:'), error.message); } throw error; } } // Recent commits analysis async analyzeRecentCommits(limit = 10, config = {}) { try { return await this.appService.analyzeRecentCommits(limit, config); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Commits analysis failed:'), error.message); } throw error; } } // Branches analysis - delegates to analysis engine async analyzeBranches(config = {}) { try { return await this.appService.analyzeRepository({ ...config, type: 'branches' }); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Branches analysis failed:'), error.message); } throw error; } } // Comprehensive analysis - delegates to analysis engine async analyzeComprehensive(config = {}) { try { return await this.appService.analyzeRepository({ ...config, type: 'comprehensive' }); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Comprehensive analysis failed:'), error.message); } throw error; } } // Repository health assessment async assessRepositoryHealth(config = {}) { try { return await this.appService.assessHealth(config); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Health assessment failed:'), error.message); } throw error; } } // Working directory changelog. Mirrors generateChangelog: without `options` an // embedder cannot reach analysisMode/format/attribution/output at all. async generateChangelogFromChanges(version = null, options = {}) { try { return await this.appService.generateChangelogFromChanges(version, { analysisMode: this.analysisMode, ...options, }); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Working directory changelog failed:'), error.message); } throw error; } } // Interactive mode async runInteractive() { try { return await this.appService.runInteractive(); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Interactive mode failed:'), error.message); } throw error; } } // Health check async healthCheck() { try { return await this.appService.healthCheck(); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Health check failed:'), error.message); } throw error; } } // Commit message generation with AI and validation async generateCommitMessage(options = {}) { try { return await this.appService.generateCommitMessage(options); } catch (error) { if (!this.silent) { console.error(colors.errorMessage('Commit message generation failed:'), error.message); } throw error; } } // Configuration methods - simple delegation setAnalysisMode(mode) { this.analysisMode = mode; this.appService.setAnalysisMode(mode); } setModelOverride(model) { this.modelOverride = model; this.appService.setModelOverride(model); } // Provider management - delegates to service layer async listProviders() { return await this.appService.listProviders(); } async switchProvider(providerName) { return await this.appService.switchProvider(providerName); } async validateProvider(providerName) { return await this.appService.validateProvider(providerName); } async validateAllProviders() { return await this.appService.validateAllProviders(); } // Metrics - delegates to orchestrator getMetrics() { return this.appService.getMetrics(); } resetMetrics() { this.appService.resetMetrics(); } // Configuration validation async validateConfiguration() { return await this.appService.validateConfiguration(); } // Simple logging method log(message, type = 'info') { if (this.silent) { return; } switch (type) { case 'error': console.error(colors.errorMessage(message)); break; case 'warning': console.warn(colors.warningMessage(message)); break; case 'success': console.log(colors.successMessage(message)); break; default: console.log(colors.infoMessage(message)); } } } export default AIChangelogGenerator; // CLI integration point (would be moved to separate CLI file) export async function createGenerator(options = {}) { try { const generator = new AIChangelogGenerator(options); // Perform health check on initialization const health = await generator.healthCheck(); if (health.status === 'unhealthy') { console.warn(colors.warningMessage('⚠️ Health check failed:')); Object.entries(health.checks).forEach(([check, result]) => { if (result.status === 'error') { console.warn(colors.errorMessage(` ❌ ${check}: ${result.message}`)); } }); } return generator; } catch (error) { console.error(colors.errorMessage('Failed to create generator:'), error.message); throw error; } }