UNPKG

github-mcp-auto-git

Version:

GitHub MCP Auto Git v3.0 - メモリ効率化・統合MCP・モジュール化完了の完全自動Git操作システム

338 lines 13.4 kB
/** * System Status Manager Module * Handles system health monitoring and status reporting following Constitutional AI principles */ import { join } from 'path'; import { promises as fs } from 'fs'; export class SystemStatusManager { constructor(config) { this.metrics = { processedFiles: 0, successfulCommits: 0, failedOperations: 0, processingTimes: [] }; this.config = config; this.startTime = Date.now(); } /** * Get comprehensive system status * Fail Fast: Immediate health assessment with early warning detection * Be Lazy: Cached status computation for efficiency * TypeScript First: Complete type safety for status reporting */ async getSystemStatus() { const health = await this.assessSystemHealth(); return { enabled: this.config.enabled, watching: health.components.fileWatcher === 'active', processing: health.components.gitOperations === 'busy', agents: this.getEnabledAgents(), config: this.config, health }; } /** * Assess comprehensive system health * Fail Fast: Proactive health monitoring with immediate issue detection */ async assessSystemHealth() { const warnings = []; const recommendations = []; // Check component health const components = { fileWatcher: this.assessFileWatcherHealth(), gitOperations: this.assessGitOperationsHealth(), subagents: this.assessSubagentsHealth(), configuration: this.assessConfigurationHealth() }; // Collect warnings and recommendations if (components.configuration === 'incomplete') { warnings.push('GitHub token not configured - PR functionality disabled'); recommendations.push('Set GITHUB_TOKEN for full functionality'); } if (components.subagents === 'partial') { warnings.push('Some subagents are disabled'); recommendations.push('Enable all subagents for optimal performance'); } // Calculate metrics const uptime = Date.now() - this.startTime; const avgProcessingTime = this.metrics.processingTimes.length > 0 ? this.metrics.processingTimes.reduce((a, b) => a + b, 0) / this.metrics.processingTimes.length : 0; const metrics = { uptime, processedFiles: this.metrics.processedFiles, successfulCommits: this.metrics.successfulCommits, failedOperations: this.metrics.failedOperations, averageProcessingTime: avgProcessingTime }; // Determine overall health const overall = this.calculateOverallHealth(components, metrics, warnings); return { overall, components, metrics, warnings, recommendations }; } /** * Start periodic health checks * Be Lazy: Configurable health check intervals */ startHealthMonitoring(intervalMs = 30000) { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); } this.healthCheckInterval = setInterval(() => { this.performPeriodicHealthCheck(); }, intervalMs); console.log(`💓 健康監視開始: ${intervalMs / 1000}秒間隔`); } /** * Stop health monitoring * Fail Fast: Clean resource cleanup */ stopHealthMonitoring() { if (this.healthCheckInterval) { clearInterval(this.healthCheckInterval); this.healthCheckInterval = undefined; console.log('🛑 健康監視停止'); } } /** * Record processing metrics * TypeScript First: Strongly typed metrics recording */ recordProcessingMetrics(success, processingTime, filesProcessed = 1) { this.metrics.processedFiles += filesProcessed; this.metrics.processingTimes.push(processingTime); // Keep only last 100 processing times for average calculation if (this.metrics.processingTimes.length > 100) { this.metrics.processingTimes = this.metrics.processingTimes.slice(-100); } if (success) { this.metrics.successfulCommits++; } else { this.metrics.failedOperations++; } } /** * Manage PID file operations * Fail Fast: Robust PID file management with error handling */ async managePIDFile() { const pidFilePath = join(process.cwd(), '.github-auto-git.pid'); return { create: async () => { try { await fs.writeFile(pidFilePath, process.pid.toString()); console.log(`📄 PIDファイル作成: ${pidFilePath}`); } catch (error) { console.warn('⚠️ PIDファイル作成に失敗:', error); throw new Error(`PID file creation failed: ${error}`); } }, remove: async () => { try { await fs.unlink(pidFilePath); console.log('🗑️ PIDファイルを削除しました'); } catch (error) { // PID file might not exist, which is acceptable if (error.code !== 'ENOENT') { console.warn('⚠️ PIDファイル削除に失敗:', error); } } }, check: async () => { try { const pidString = await fs.readFile(pidFilePath, 'utf-8'); const pid = parseInt(pidString.trim(), 10); // Check if process is still running let isRunning = false; try { process.kill(pid, 0); // Signal 0 checks if process exists isRunning = true; } catch { isRunning = false; } return { exists: true, pid, isRunning, filePath: pidFilePath }; } catch (error) { return { exists: false, filePath: pidFilePath }; } } }; } /** * Display formatted system status * Be Lazy: Efficient status formatting with visual indicators */ displaySystemStatus(health) { console.log('\n📊 システム状態レポート'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // Overall health indicator const healthIcon = this.getHealthIcon(health.overall); console.log(`${healthIcon} 総合健康状態: ${health.overall.toUpperCase()}`); // Component status console.log('\n🔧 コンポーネント状態:'); console.log(` 📂 ファイル監視: ${this.getComponentStatusIcon(health.components.fileWatcher)} ${health.components.fileWatcher}`); console.log(` 🔄 Git操作: ${this.getComponentStatusIcon(health.components.gitOperations)} ${health.components.gitOperations}`); console.log(` 🤖 サブエージェント: ${this.getComponentStatusIcon(health.components.subagents)} ${health.components.subagents}`); console.log(` ⚙️ 設定: ${this.getComponentStatusIcon(health.components.configuration)} ${health.components.configuration}`); // Metrics console.log('\n📈 運用メトリクス:'); console.log(` ⏰ 稼働時間: ${this.formatUptime(health.metrics.uptime)}`); console.log(` 📁 処理済みファイル: ${health.metrics.processedFiles}`); console.log(` ✅ 成功コミット: ${health.metrics.successfulCommits}`); console.log(` ❌ 失敗操作: ${health.metrics.failedOperations}`); console.log(` ⚡ 平均処理時間: ${health.metrics.averageProcessingTime.toFixed(2)}ms`); // Warnings if (health.warnings.length > 0) { console.log('\n⚠️ 警告:'); health.warnings.forEach(warning => console.log(` • ${warning}`)); } // Recommendations if (health.recommendations.length > 0) { console.log('\n💡 推奨事項:'); health.recommendations.forEach(rec => console.log(` • ${rec}`)); } console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); } /** * Perform periodic health check * Fail Fast: Proactive issue detection during operation */ async performPeriodicHealthCheck() { try { const health = await this.assessSystemHealth(); if (health.overall === 'critical') { console.log('🚨 システム健康状態が危険レベルです!'); this.displaySystemStatus(health); } else if (health.overall === 'warning') { console.log('⚠️ システムに問題が検出されました'); } else { console.log(`💓 ヘルスチェック: ${new Date().toLocaleTimeString()} - ${health.overall}`); } } catch (error) { console.error('❌ ヘルスチェックエラー:', error); } } /** * Get list of enabled agents * TypeScript First: Type-safe agent enumeration */ getEnabledAgents() { const agents = []; if (this.config.subAgents.gitSafetyAnalyzer.enabled) agents.push('Git Safety Analyzer'); if (this.config.subAgents.commitMessageGenerator.enabled) agents.push('Commit Message Generator'); if (this.config.subAgents.prManagementAgent.enabled) agents.push('PR Management Agent'); return agents; } /** * Assess individual component health states * Be Lazy: Efficient component health assessment */ assessFileWatcherHealth() { // This would be updated by the FileWatchManager return 'active'; // Placeholder } assessGitOperationsHealth() { // This would be updated by the GitOperations return 'ready'; // Placeholder } assessSubagentsHealth() { const enabledCount = this.getEnabledAgents().length; const totalCount = 3; // Total number of available subagents if (enabledCount === totalCount) return 'all_enabled'; if (enabledCount > 0) return 'partial'; return 'disabled'; } assessConfigurationHealth() { if (!this.config.enabled) return 'invalid'; if (!this.config.github.token) return 'incomplete'; return 'valid'; } /** * Calculate overall system health * Fail Fast: Comprehensive health assessment with weighted scoring */ calculateOverallHealth(components, metrics, warnings) { // Critical conditions if (components.fileWatcher === 'error' || components.gitOperations === 'error') { return 'critical'; } // Warning conditions if (warnings.length > 2 || components.configuration === 'invalid') { return 'warning'; } // Good conditions if (components.subagents === 'partial' || components.configuration === 'incomplete') { return 'good'; } return 'optimal'; } /** * Get health status visual indicators * Be Lazy: Reusable status formatting */ getHealthIcon(health) { switch (health) { case 'optimal': return '🟢'; case 'good': return '🟡'; case 'warning': return '🟠'; case 'critical': return '🔴'; default: return '⚪'; } } getComponentStatusIcon(status) { if (status.includes('active') || status.includes('ready') || status.includes('all_enabled') || status.includes('valid')) { return '✅'; } if (status.includes('error') || status.includes('invalid') || status.includes('disabled')) { return '❌'; } return '⚠️'; } /** * Format uptime in human-readable format * TypeScript First: Type-safe time formatting */ formatUptime(uptime) { const seconds = Math.floor(uptime / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}日 ${hours % 24}時間 ${minutes % 60}分`; if (hours > 0) return `${hours}時間 ${minutes % 60}分`; if (minutes > 0) return `${minutes}分 ${seconds % 60}秒`; return `${seconds}秒`; } } //# sourceMappingURL=system-status-manager.js.map