import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { logger } from "../../../core/monitoring/logger.js";
import { FrameManager } from "../../../core/context/index.js";
import { sharedContextLayer } from "../../../core/context/shared-context-layer.js";
import { sessionManager } from "../../../core/session/index.js";
class PatternLearner {
  frameManager;
  config;
  constructor(config) {
    this.config = {
      minLoopCountForPattern: 3,
      confidenceThreshold: 0.7,
      maxPatternsPerType: 10,
      analysisDepth: "deep",
      ...config
    };
    logger.info("Pattern learner initialized", this.config);
  }
  async initialize() {
    try {
      await sessionManager.initialize();
      await sharedContextLayer.initialize();
      const session = await sessionManager.getOrCreateSession({});
      if (session.database) {
        this.frameManager = new FrameManager(session.database, session.projectId);
      }
      logger.info("Pattern learner initialized successfully");
    } catch (error) {
      logger.error("Failed to initialize pattern learner", error);
      throw error;
    }
  }
  /**
   * Learn patterns from all completed Ralph loops
   */
  async learnFromCompletedLoops() {
    logger.info("Starting pattern learning from completed loops");
    try {
      const completedLoops = await this.getCompletedRalphLoops();
      logger.info(`Found ${completedLoops.length} completed loops for analysis`);
      if (completedLoops.length < this.config.minLoopCountForPattern) {
        logger.info("Not enough loops for pattern extraction");
        return [];
      }
      const patterns = [];
      const successPatterns = await this.extractSuccessPatterns(completedLoops);
      patterns.push(...successPatterns);
      const failurePatterns = await this.extractFailurePatterns(completedLoops);
      patterns.push(...failurePatterns);
      const iterationPatterns = await this.extractIterationPatterns(completedLoops);
      patterns.push(...iterationPatterns);
      const taskPatterns = await this.extractTaskPatterns(completedLoops);
      patterns.push(...taskPatterns);
      await this.saveLearnedPatterns(patterns);
      logger.info(`Learned ${patterns.length} patterns from ${completedLoops.length} loops`);
      return patterns;
    } catch (error) {
      logger.error("Failed to learn patterns", error);
      throw error;
    }
  }
  /**
   * Learn patterns specific to a task type
   */
  async learnForTaskType(taskType) {
    logger.info(`Learning patterns for task type: ${taskType}`);
    const completedLoops = await this.getCompletedRalphLoops();
    const relevantLoops = completedLoops.filter(
      (loop) => this.classifyTaskType(loop.task) === taskType
    );
    if (relevantLoops.length < this.config.minLoopCountForPattern) {
      return [];
    }
    return this.extractSpecializedPatterns(relevantLoops, taskType);
  }
  /**
   * Get all completed Ralph loops from StackMemory
   */
  async getCompletedRalphLoops() {
    if (!this.frameManager) {
      throw new Error("Frame manager not initialized");
    }
    try {
      const ralphFrames = await this.frameManager.searchFrames({
        type: "task",
        namePattern: "ralph-*",
        state: "closed"
      });
      const analyses = [];
      for (const frame of ralphFrames) {
        try {
          const analysis = await this.analyzeCompletedLoop(frame);
          if (analysis) {
            analyses.push(analysis);
          }
        } catch (error) {
          logger.warn(`Failed to analyze loop ${frame.frame_id}`, error);
        }
      }
      return analyses;
    } catch (error) {
      logger.error("Failed to get completed loops", error);
      return [];
    }
  }
  /**
   * Analyze a completed loop for patterns
   */
  async analyzeCompletedLoop(ralphFrame) {
    if (!this.frameManager) return null;
    try {
      const loopState = ralphFrame.inputs;
      const iterationFrames = await this.frameManager.searchFrames({
        type: "subtask",
        namePattern: "iteration-*",
        parentId: ralphFrame.frame_id
      });
      const successMetrics = this.calculateSuccessMetrics(iterationFrames);
      const iterationAnalysis = this.analyzeIterations(iterationFrames);
      const outcome = this.determineLoopOutcome(ralphFrame, iterationFrames);
      return {
        loopId: loopState.loopId,
        task: loopState.task,
        criteria: loopState.criteria,
        taskType: this.classifyTaskType(loopState.task),
        iterationCount: iterationFrames.length,
        outcome,
        successMetrics,
        iterationAnalysis,
        duration: ralphFrame.updated_at - ralphFrame.created_at,
        startTime: ralphFrame.created_at,
        endTime: ralphFrame.updated_at
      };
    } catch (error) {
      logger.error("Failed to analyze loop", error);
      return null;
    }
  }
  /**
   * Extract patterns from successful loops
   */
  async extractSuccessPatterns(loops) {
    const successfulLoops = loops.filter((l) => l.outcome === "success");
    if (successfulLoops.length < this.config.minLoopCountForPattern) {
      return [];
    }
    const patterns = [];
    const avgIterations = successfulLoops.reduce((sum, l) => sum + l.iterationCount, 0) / successfulLoops.length;
    patterns.push({
      id: "optimal-iterations",
      type: "iteration_strategy",
      pattern: `Successful tasks typically complete in ${Math.round(avgIterations)} iterations`,
      confidence: this.calculateConfidence(successfulLoops.length),
      frequency: successfulLoops.length,
      strategy: `Target ${Math.round(avgIterations)} iterations for similar tasks`,
      examples: successfulLoops.slice(0, 3).map((l) => l.task),
      metadata: {
        avgIterations,
        minIterations: Math.min(...successfulLoops.map((l) => l.iterationCount)),
        maxIterations: Math.max(...successfulLoops.map((l) => l.iterationCount))
      }
    });
    const criteriaPatterns = this.extractCriteriaPatterns(successfulLoops);
    patterns.push(...criteriaPatterns);
    const successFactors = this.extractSuccessFactors(successfulLoops);
    patterns.push(...successFactors);
    return patterns.filter((p) => p.confidence >= this.config.confidenceThreshold);
  }
  /**
   * Extract patterns from failed loops to avoid
   */
  async extractFailurePatterns(loops) {
    const failedLoops = loops.filter((l) => l.outcome === "failure");
    if (failedLoops.length < this.config.minLoopCountForPattern) {
      return [];
    }
    const patterns = [];
    const commonFailures = this.analyzeFailurePoints(failedLoops);
    for (const failure of commonFailures) {
      patterns.push({
        id: `avoid-${failure.type}`,
        type: "failure_avoidance",
        pattern: `Avoid: ${failure.pattern}`,
        confidence: this.calculateConfidence(failure.frequency),
        frequency: failure.frequency,
        strategy: failure.avoidanceStrategy,
        examples: failure.examples,
        metadata: { failureType: failure.type }
      });
    }
    return patterns.filter((p) => p.confidence >= this.config.confidenceThreshold);
  }
  /**
   * Extract iteration-specific patterns
   */
  async extractIterationPatterns(loops) {
    const patterns = [];
    const iterationSequences = this.analyzeIterationSequences(loops);
    for (const sequence of iterationSequences) {
      if (sequence.frequency >= this.config.minLoopCountForPattern) {
        patterns.push({
          id: `iteration-sequence-${sequence.id}`,
          type: "iteration_sequence",
          pattern: sequence.description,
          confidence: this.calculateConfidence(sequence.frequency),
          frequency: sequence.frequency,
          strategy: sequence.strategy,
          examples: sequence.examples,
          metadata: { sequenceType: sequence.type }
        });
      }
    }
    return patterns;
  }
  /**
   * Extract task-specific patterns
   */
  async extractTaskPatterns(loops) {
    const taskGroups = this.groupByTaskType(loops);
    const patterns = [];
    for (const [taskType, taskLoops] of Object.entries(taskGroups)) {
      if (taskLoops.length >= this.config.minLoopCountForPattern) {
        const taskSpecificPatterns = await this.extractSpecializedPatterns(taskLoops, taskType);
        patterns.push(...taskSpecificPatterns);
      }
    }
    return patterns;
  }
  /**
   * Extract specialized patterns for specific task types
   */
  async extractSpecializedPatterns(loops, taskType) {
    const patterns = [];
    const successful = loops.filter((l) => l.outcome === "success");
    if (successful.length === 0) return patterns;
    patterns.push({
      id: `${taskType}-success-pattern`,
      type: "task_specific",
      pattern: `${taskType} tasks: ${this.summarizeSuccessPattern(successful)}`,
      confidence: this.calculateConfidence(successful.length),
      frequency: successful.length,
      strategy: this.generateTaskStrategy(successful),
      examples: successful.slice(0, 2).map((l) => l.task),
      metadata: { taskType, totalAttempts: loops.length }
    });
    return patterns;
  }
  /**
   * Calculate success metrics for iterations
   */
  calculateSuccessMetrics(iterations) {
    const total = iterations.length;
    const successful = iterations.filter((i) => i.outputs?.success).length;
    return {
      iterationCount: total,
      successRate: total > 0 ? successful / total : 0,
      averageProgress: this.calculateAverageProgress(iterations),
      timeToCompletion: total > 0 ? iterations[total - 1].updated_at - iterations[0].created_at : 0
    };
  }
  /**
   * Classify task type based on description
   */
  classifyTaskType(task) {
    const taskLower = task.toLowerCase();
    if (taskLower.includes("test") || taskLower.includes("unit")) return "testing";
    if (taskLower.includes("fix") || taskLower.includes("bug")) return "bugfix";
    if (taskLower.includes("refactor")) return "refactoring";
    if (taskLower.includes("add") || taskLower.includes("implement")) return "feature";
    if (taskLower.includes("document")) return "documentation";
    if (taskLower.includes("optimize") || taskLower.includes("performance")) return "optimization";
    return "general";
  }
  /**
   * Determine loop outcome
   */
  determineLoopOutcome(ralphFrame, iterations) {
    if (ralphFrame.digest_json?.status === "completed") return "success";
    if (iterations.length === 0) return "unknown";
    const lastIteration = iterations[iterations.length - 1];
    if (lastIteration.outputs?.success) return "success";
    return "failure";
  }
  /**
   * Calculate confidence based on frequency
   */
  calculateConfidence(frequency) {
    return Math.min(0.95, Math.log(frequency + 1) / Math.log(10));
  }
  /**
   * Save learned patterns to shared context
   */
  async saveLearnedPatterns(patterns) {
    try {
      const context = await sharedContextLayer.getSharedContext();
      if (!context) return;
      const contextPatterns = patterns.map((p) => ({
        pattern: p.pattern,
        type: this.mapPatternType(p.type),
        frequency: p.frequency,
        lastSeen: Date.now(),
        resolution: p.strategy
      }));
      context.globalPatterns.push(...contextPatterns);
      context.globalPatterns.sort((a, b) => b.frequency - a.frequency);
      context.globalPatterns = context.globalPatterns.slice(0, 100);
      await sharedContextLayer.updateSharedContext(context);
      logger.info(`Saved ${patterns.length} patterns to shared context`);
    } catch (error) {
      logger.error("Failed to save patterns", error);
    }
  }
  /**
   * Map pattern types to shared context types
   */
  mapPatternType(patternType) {
    switch (patternType) {
      case "failure_avoidance":
        return "error";
      case "success_strategy":
        return "success";
      case "task_specific":
        return "learning";
      default:
        return "learning";
    }
  }
  // Additional helper methods for pattern analysis
  analyzeIterations(iterations) {
    return {
      avgDuration: iterations.length > 0 ? iterations.reduce((sum, i) => sum + (i.updated_at - i.created_at), 0) / iterations.length : 0,
      progressPattern: this.extractProgressPattern(iterations),
      commonIssues: this.extractCommonIssues(iterations)
    };
  }
  extractProgressPattern(iterations) {
    const progressSteps = iterations.map((_, i) => {
      const progress = i / iterations.length;
      return Math.round(progress * 100);
    });
    return progressSteps.join(" \u2192 ") + "%";
  }
  extractCommonIssues(iterations) {
    return iterations.filter((i) => i.outputs?.errors?.length > 0).flatMap((i) => i.outputs.errors).slice(0, 3);
  }
  extractCriteriaPatterns(loops) {
    const criteriaWords = loops.flatMap((l) => l.criteria.toLowerCase().split(/\s+/));
    const wordCounts = criteriaWords.reduce((acc, word) => {
      acc[word] = (acc[word] || 0) + 1;
      return acc;
    }, {});
    const commonCriteria = Object.entries(wordCounts).filter(([_, count]) => count >= this.config.minLoopCountForPattern).sort((a, b) => b[1] - a[1]).slice(0, 3);
    return commonCriteria.map(([word, count]) => ({
      id: `criteria-${word}`,
      type: "success_strategy",
      pattern: `Successful tasks often include "${word}" in completion criteria`,
      confidence: this.calculateConfidence(count),
      frequency: count,
      strategy: `Consider including "${word}" in task completion criteria`,
      examples: loops.filter((l) => l.criteria.toLowerCase().includes(word)).slice(0, 2).map((l) => l.task),
      metadata: { criteriaWord: word }
    }));
  }
  extractSuccessFactors(loops) {
    return [];
  }
  analyzeFailurePoints(loops) {
    return [];
  }
  analyzeIterationSequences(loops) {
    return [];
  }
  groupByTaskType(loops) {
    return loops.reduce((acc, loop) => {
      const type = loop.taskType;
      if (!acc[type]) acc[type] = [];
      acc[type].push(loop);
      return acc;
    }, {});
  }
  summarizeSuccessPattern(loops) {
    const avgIterations = loops.reduce((sum, l) => sum + l.iterationCount, 0) / loops.length;
    return `typically complete in ${Math.round(avgIterations)} iterations with ${Math.round(loops[0]?.successMetrics?.successRate * 100 || 0)}% success rate`;
  }
  generateTaskStrategy(loops) {
    const avgIterations = loops.reduce((sum, l) => sum + l.iterationCount, 0) / loops.length;
    return `Plan for approximately ${Math.round(avgIterations)} iterations and focus on iterative improvement`;
  }
  calculateAverageProgress(iterations) {
    return iterations.length > 0 ? iterations.length / 10 : 0;
  }
}
const patternLearner = new PatternLearner();
export {
  PatternLearner,
  patternLearner
};
//# sourceMappingURL=pattern-learner.js.map
