autoagent-cli
Version:
Run autonomous AI agents using Claude or Gemini for task execution
227 lines (226 loc) • 9.03 kB
JavaScript
;
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;