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/frame-manager.js";
import { sharedContextLayer } from "../../../core/context/shared-context-layer.js";
import { ContextRetriever } from "../../../core/retrieval/context-retriever.js";
import { sessionManager } from "../../../core/session/index.js";
import { ContextBudgetManager } from "./context-budget-manager.js";
class StackMemoryContextLoader {
  frameManager;
  contextRetriever;
  budgetManager;
  config;
  constructor(config) {
    this.config = {
      maxTokens: 3200,
      // Leave room for task description
      lookbackDays: 30,
      similarityThreshold: 0.7,
      patternDetectionEnabled: true,
      includeFailedAttempts: true,
      crossSessionSearch: true,
      ...config
    };
    this.budgetManager = new ContextBudgetManager({
      maxTokens: this.config.maxTokens,
      priorityWeights: {
        task: 0.15,
        recentWork: 0.3,
        patterns: 0.25,
        decisions: 0.2,
        dependencies: 0.1
      }
    });
    logger.info("StackMemory context loader initialized", {
      maxTokens: this.config.maxTokens,
      lookbackDays: this.config.lookbackDays,
      patternDetection: this.config.patternDetectionEnabled
    });
  }
  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);
        this.contextRetriever = new ContextRetriever(session.database);
      }
      logger.info("Context loader initialized successfully");
    } catch (error) {
      logger.error("Failed to initialize context loader", error);
      throw error;
    }
  }
  /**
   * Load context for Ralph loop initialization
   */
  async loadInitialContext(request) {
    logger.info("Loading initial context for Ralph loop", {
      task: request.task.substring(0, 100),
      usePatterns: request.usePatterns,
      useSimilarTasks: request.useSimilarTasks
    });
    const sources = [];
    let totalTokens = 0;
    try {
      if (request.useSimilarTasks) {
        const similarTasks2 = await this.findSimilarTasks(request.task);
        if (similarTasks2.length > 0) {
          const tasksContext = await this.extractTaskContext(similarTasks2);
          sources.push({
            type: "similar_tasks",
            weight: 0.3,
            content: tasksContext,
            tokens: this.budgetManager.estimateTokens(tasksContext)
          });
          totalTokens += sources[sources.length - 1].tokens;
        }
      }
      if (request.usePatterns) {
        const patterns2 = await this.extractRelevantPatterns(request.task);
        if (patterns2.length > 0) {
          const patternsContext = await this.formatPatterns(patterns2);
          sources.push({
            type: "historical_patterns",
            weight: 0.25,
            content: patternsContext,
            tokens: this.budgetManager.estimateTokens(patternsContext)
          });
          totalTokens += sources[sources.length - 1].tokens;
        }
      }
      const decisions = await this.loadRecentDecisions();
      if (decisions.length > 0) {
        const decisionsContext = this.formatDecisions(decisions);
        sources.push({
          type: "recent_decisions",
          weight: 0.2,
          content: decisionsContext,
          tokens: this.budgetManager.estimateTokens(decisionsContext)
        });
        totalTokens += sources[sources.length - 1].tokens;
      }
      const projectContext = await this.loadProjectContext(request.task);
      if (projectContext) {
        sources.push({
          type: "project_context",
          weight: 0.15,
          content: projectContext,
          tokens: this.budgetManager.estimateTokens(projectContext)
        });
        totalTokens += sources[sources.length - 1].tokens;
      }
      const budgetedSources = this.budgetManager.allocateBudget({ sources });
      const synthesizedContext = this.synthesizeContext(budgetedSources.sources);
      logger.info("Context loaded successfully", {
        totalSources: sources.length,
        totalTokens,
        budgetedTokens: budgetedSources.sources.reduce((sum, s) => sum + s.tokens, 0)
      });
      return {
        context: synthesizedContext,
        sources: budgetedSources.sources,
        metadata: {
          totalTokens: budgetedSources.sources.reduce((sum, s) => sum + s.tokens, 0),
          sourcesCount: budgetedSources.sources.length,
          patterns: request.usePatterns ? patterns : [],
          similarTasks: request.useSimilarTasks ? similarTasks : []
        }
      };
    } catch (error) {
      logger.error("Failed to load context", error);
      throw error;
    }
  }
  /**
   * Find similar tasks from StackMemory history
   */
  async findSimilarTasks(taskDescription) {
    if (!this.frameManager || !this.contextRetriever) {
      return [];
    }
    try {
      const searchResults = await this.contextRetriever.search(taskDescription, {
        maxResults: 10,
        types: ["task", "subtask"],
        timeFilter: {
          days: this.config.lookbackDays
        }
      });
      const similarities = [];
      for (const result of searchResults) {
        const similarity = this.calculateTaskSimilarity(taskDescription, result.content);
        if (similarity >= this.config.similarityThreshold) {
          similarities.push({
            frameId: result.frameId,
            task: result.content,
            similarity,
            outcome: await this.determineTaskOutcome(result.frameId),
            createdAt: result.timestamp,
            sessionId: result.sessionId || "unknown"
          });
        }
      }
      return similarities.sort((a, b) => {
        const aScore = a.similarity * (a.outcome === "success" ? 1.2 : 1);
        const bScore = b.similarity * (b.outcome === "success" ? 1.2 : 1);
        return bScore - aScore;
      }).slice(0, 5);
    } catch (error) {
      logger.error("Failed to find similar tasks", error);
      return [];
    }
  }
  /**
   * Extract relevant patterns from historical data
   */
  async extractRelevantPatterns(taskDescription) {
    try {
      const context = await sharedContextLayer.getSharedContext();
      if (!context) return [];
      const relevantPatterns = [];
      for (const pattern of context.globalPatterns) {
        const relevance = this.calculatePatternRelevance(taskDescription, pattern.pattern);
        if (relevance >= 0.5) {
          relevantPatterns.push({
            pattern: pattern.pattern,
            type: pattern.type,
            frequency: pattern.frequency,
            lastSeen: pattern.lastSeen,
            relevance,
            resolution: pattern.resolution,
            examples: await this.getPatternExamples(pattern.pattern)
          });
        }
      }
      return relevantPatterns.sort((a, b) => b.relevance * Math.log(b.frequency + 1) - a.relevance * Math.log(a.frequency + 1)).slice(0, 8);
    } catch (error) {
      logger.error("Failed to extract patterns", error);
      return [];
    }
  }
  /**
   * Load recent decisions that might be relevant
   */
  async loadRecentDecisions() {
    try {
      const context = await sharedContextLayer.getSharedContext();
      if (!context) return [];
      const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
      return context.decisionLog.filter((d) => d.timestamp >= cutoff && d.outcome === "success").sort((a, b) => b.timestamp - a.timestamp).slice(0, 5);
    } catch (error) {
      logger.error("Failed to load recent decisions", error);
      return [];
    }
  }
  /**
   * Load project-specific context
   */
  async loadProjectContext(taskDescription) {
    try {
      if (!this.contextRetriever) return null;
      const projectInfo = await this.contextRetriever.search(taskDescription, {
        maxResults: 3,
        types: ["task"],
        projectSpecific: true
      });
      if (projectInfo.length === 0) return null;
      const contextParts = [];
      for (const info of projectInfo) {
        contextParts.push(`Project context: ${info.content}`);
      }
      return contextParts.join("\n\n");
    } catch (error) {
      logger.error("Failed to load project context", error);
      return null;
    }
  }
  /**
   * Calculate similarity between task descriptions
   */
  calculateTaskSimilarity(task1, task2) {
    const words1 = new Set(task1.toLowerCase().split(/\s+/));
    const words2 = new Set(task2.toLowerCase().split(/\s+/));
    const intersection = new Set([...words1].filter((x) => words2.has(x)));
    const union = /* @__PURE__ */ new Set([...words1, ...words2]);
    return intersection.size / union.size;
  }
  /**
   * Calculate pattern relevance to current task
   */
  calculatePatternRelevance(taskDescription, pattern) {
    const taskWords = taskDescription.toLowerCase().split(/\s+/);
    const patternWords = pattern.toLowerCase().split(/\s+/);
    let matches = 0;
    for (const word of taskWords) {
      if (patternWords.some((p) => p.includes(word) || word.includes(p))) {
        matches++;
      }
    }
    return matches / taskWords.length;
  }
  /**
   * Extract context from similar tasks
   */
  async extractTaskContext(similarities) {
    const contextParts = [];
    contextParts.push("Similar tasks from history:");
    for (const sim of similarities) {
      contextParts.push(`
Task: ${sim.task}
Outcome: ${sim.outcome}
Similarity: ${Math.round(sim.similarity * 100)}%
${sim.outcome === "success" ? "\u2705 Successfully completed" : "\u274C Had issues"}
      `.trim());
    }
    return contextParts.join("\n\n");
  }
  /**
   * Format patterns for context inclusion
   */
  async formatPatterns(patterns2) {
    const contextParts = [];
    contextParts.push("Relevant patterns from experience:");
    for (const pattern of patterns2) {
      contextParts.push(`
Pattern: ${pattern.pattern}
Type: ${pattern.type}
Frequency: ${pattern.frequency} occurrences
${pattern.resolution ? `Resolution: ${pattern.resolution}` : ""}
Relevance: ${Math.round(pattern.relevance * 100)}%
      `.trim());
    }
    return contextParts.join("\n\n");
  }
  /**
   * Format decisions for context inclusion
   */
  formatDecisions(decisions) {
    const contextParts = [];
    contextParts.push("Recent successful decisions:");
    for (const decision of decisions) {
      contextParts.push(`
Decision: ${decision.decision}
Reasoning: ${decision.reasoning}
Date: ${new Date(decision.timestamp).toLocaleDateString()}
      `.trim());
    }
    return contextParts.join("\n\n");
  }
  /**
   * Synthesize all context sources into coherent input
   */
  synthesizeContext(sources) {
    if (sources.length === 0) {
      return "No relevant historical context found.";
    }
    const contextParts = [];
    contextParts.push("Context from StackMemory:");
    const sortedSources = sources.sort((a, b) => b.weight - a.weight);
    for (const source of sortedSources) {
      contextParts.push(`
--- ${source.type.replace("_", " ").toUpperCase()} ---`);
      contextParts.push(source.content);
    }
    contextParts.push("\nUse this context to inform your approach to the current task.");
    return contextParts.join("\n");
  }
  /**
   * Determine task outcome from frame history
   */
  async determineTaskOutcome(frameId) {
    try {
      if (!this.frameManager) return "unknown";
      const frame = await this.frameManager.getFrame(frameId);
      if (!frame) return "unknown";
      if (frame.state === "closed" && frame.outputs) {
        return "success";
      }
      return frame.state === "closed" ? "failure" : "unknown";
    } catch {
      return "unknown";
    }
  }
  /**
   * Get examples of a specific pattern
   */
  async getPatternExamples(pattern) {
    return [];
  }
}
const stackMemoryContextLoader = new StackMemoryContextLoader();
export {
  StackMemoryContextLoader,
  stackMemoryContextLoader
};
//# sourceMappingURL=stackmemory-context-loader.js.map
