UNPKG

autoagent-cli

Version:

Run autonomous AI agents using Claude or Gemini for task execution

227 lines (226 loc) 9.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PatternAnalyzer = void 0; class PatternAnalyzer { constructor() { this.executionHistory = []; this.patterns = new Map(); } addExecution(result) { this.executionHistory.push(result); this.analyzePatterns(); } analyzePatterns() { this.patterns.clear(); this.analyzeSuccessPatterns(); this.analyzeFailurePatterns(); this.analyzeFileChangePatterns(); this.analyzeDurationPatterns(); this.analyzeProviderPatterns(); } analyzeSuccessPatterns() { const successfulExecutions = this.executionHistory.filter(e => e.success); const totalExecutions = this.executionHistory.length; if (totalExecutions === 0) { return; } const successRate = successfulExecutions.length / totalExecutions; if (successRate >= 0.95) { this.addPattern({ name: 'high-success-rate', description: 'Consistently successful execution pattern', confidence: Math.min(totalExecutions / 10, 1), occurrences: successfulExecutions.length }); } else if (successRate < 0.7) { this.addPattern({ name: 'high-failure-rate', description: 'Frequent failures requiring investigation', confidence: Math.min(totalExecutions / 10, 1), occurrences: totalExecutions - successfulExecutions.length }); } } analyzeFailurePatterns() { const failures = this.executionHistory.filter(e => !e.success && e.error); const errorTypes = new Map(); failures.forEach(failure => { if (failure.error !== undefined && failure.error !== '') { const errorType = this.categorizeError(failure.error); errorTypes.set(errorType, (errorTypes.get(errorType) ?? 0) + 1); } }); errorTypes.forEach((count, errorType) => { if (count >= 3) { this.addPattern({ name: `frequent-${errorType}`, description: `Recurring ${errorType} errors`, confidence: count / Math.max(failures.length, 1), occurrences: count }); } }); } categorizeError(error) { const lowerError = error.toLowerCase(); if (lowerError.includes('rate limit')) { return 'rate-limit'; } else if (lowerError.includes('timeout')) { return 'timeout'; } else if (lowerError.includes('permission') || lowerError.includes('access')) { return 'permission'; } else if (lowerError.includes('not found') || lowerError.includes('404')) { return 'not-found'; } else if (lowerError.includes('syntax') || lowerError.includes('parse')) { return 'syntax'; } else { return 'unknown'; } } analyzeFileChangePatterns() { const executionsWithFiles = this.executionHistory.filter(e => e.filesModified && e.filesModified.length > 0); if (executionsWithFiles.length < 3) { return; } const extensionCounts = new Map(); let totalFiles = 0; executionsWithFiles.forEach(execution => { execution.filesModified?.forEach(file => { totalFiles++; const ext = this.getFileExtension(file); extensionCounts.set(ext, (extensionCounts.get(ext) ?? 0) + 1); }); }); extensionCounts.forEach((count, ext) => { const percentage = count / totalFiles; if (percentage > 0.3) { this.addPattern({ name: `frequent-${ext}-changes`, description: `High frequency of ${ext} file modifications`, confidence: percentage, occurrences: count }); } }); const testFiles = this.executionHistory.filter(e => e.filesModified?.some(f => f.includes('test') || f.includes('spec'))).length; if (testFiles / executionsWithFiles.length > 0.7) { this.addPattern({ name: 'test-focused', description: 'Strong focus on test file modifications', confidence: 0.8, occurrences: testFiles }); } } analyzeDurationPatterns() { const durations = this.executionHistory .filter(e => e.duration > 0) .map(e => e.duration); if (durations.length < 5) { return; } const avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length; const stdDev = Math.sqrt(durations.reduce((sum, d) => sum + Math.pow(d - avgDuration, 2), 0) / durations.length); if (avgDuration < 30000 && stdDev < 10000) { this.addPattern({ name: 'fast-execution', description: 'Consistently fast execution times', confidence: Math.min(durations.length / 10, 1), occurrences: durations.length }); } if (stdDev > avgDuration * 0.5) { this.addPattern({ name: 'variable-duration', description: 'Highly variable execution times', confidence: 0.7, occurrences: durations.length }); } } analyzeProviderPatterns() { const providerCounts = new Map(); const providerSuccesses = new Map(); this.executionHistory.forEach(execution => { if (execution.provider) { providerCounts.set(execution.provider, (providerCounts.get(execution.provider) ?? 0) + 1); if (execution.success) { providerSuccesses.set(execution.provider, (providerSuccesses.get(execution.provider) ?? 0) + 1); } } }); providerCounts.forEach((count, provider) => { const totalExecutions = this.executionHistory.length; const usage = count / totalExecutions; if (usage > 0.8) { this.addPattern({ name: `${provider}-dominant`, description: `Heavy reliance on ${provider} provider`, confidence: usage, occurrences: count }); } const successes = providerSuccesses.get(provider) ?? 0; const successRate = successes / count; if (count >= 5 && successRate < 0.6) { this.addPattern({ name: `${provider}-struggles`, description: `${provider} provider has lower success rate`, confidence: Math.min(count / 10, 1), occurrences: count - successes }); } }); } getFileExtension(filePath) { const parts = filePath.split('.'); return parts.length > 1 ? (parts[parts.length - 1] ?? 'no-ext') : 'no-ext'; } addPattern(pattern) { this.patterns.set(pattern.name, pattern); } getExecutionCount() { return this.executionHistory.length; } getPatterns() { return Array.from(this.patterns.values()) .sort((a, b) => b.confidence - a.confidence); } getRecommendations() { const recommendations = []; const patterns = this.getPatterns(); patterns.forEach(pattern => { switch (pattern.name) { case 'high-failure-rate': recommendations.push('Consider reviewing error logs and adjusting AGENT.md instructions'); break; case 'frequent-rate-limit': recommendations.push('Implement better rate limit handling or increase delay between requests'); break; case 'variable-duration': recommendations.push('Consider breaking down complex tasks into smaller, more predictable units'); break; case 'test-focused': recommendations.push('Good testing practices detected - maintain this pattern'); break; default: if (pattern.name.includes('-struggles')) { const provider = pattern.name.replace('-struggles', ''); recommendations.push(`Consider updating ${provider.toUpperCase()}.md with more specific instructions`); } } }); return [...new Set(recommendations)]; } clear() { this.executionHistory = []; this.patterns.clear(); } } exports.PatternAnalyzer = PatternAnalyzer;