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";
const DEFAULT_CONFIG = {
  enabled: !!process.env.DIFFMEM_ENDPOINT,
  endpoint: process.env.DIFFMEM_ENDPOINT || "http://localhost:3100",
  autoFetchCategories: ["preference", "expertise", "pattern"],
  autoLearnEnabled: true,
  learningConfidenceThreshold: 0.7,
  maxMemoriesPerSession: 50
};
class DiffMemHooks {
  config;
  fetchedMemories = [];
  learningBuffer = [];
  isConnected = false;
  frameManager;
  sessionStartTime = 0;
  constructor(config = {}) {
    this.config = { ...DEFAULT_CONFIG, ...config };
  }
  /**
   * Register session hooks with the event emitter
   */
  register(emitter, frameManager) {
    this.frameManager = frameManager;
    if (!this.config.enabled) {
      logger.debug("DiffMem hooks disabled - skipping registration");
      return;
    }
    emitter.registerHandler("session_start", this.onSessionStart.bind(this));
    emitter.registerHandler("session_end", this.onSessionEnd.bind(this));
    logger.info("DiffMem hooks registered", {
      endpoint: this.config.endpoint,
      autoFetchCategories: this.config.autoFetchCategories,
      autoLearnEnabled: this.config.autoLearnEnabled
    });
  }
  /**
   * Handle session start - fetch user knowledge
   */
  async onSessionStart(event) {
    const sessionEvent = event;
    this.sessionStartTime = Date.now();
    try {
      const status = await this.checkStatus();
      this.isConnected = status.connected;
      if (!this.isConnected) {
        logger.debug("DiffMem not available - skipping memory fetch");
        return;
      }
      const query = {
        categories: this.config.autoFetchCategories,
        limit: this.config.maxMemoriesPerSession,
        minConfidence: this.config.learningConfidenceThreshold
      };
      this.fetchedMemories = await this.fetchMemories(query);
      if (this.frameManager && this.fetchedMemories.length > 0) {
        await this.injectAsAnchors(sessionEvent.data.sessionId);
      }
      logger.info("DiffMem session start completed", {
        memoriesFetched: this.fetchedMemories.length,
        sessionId: sessionEvent.data.sessionId
      });
    } catch (error) {
      logger.warn("DiffMem session start failed", {
        error: error instanceof Error ? error.message : String(error)
      });
      this.isConnected = false;
    }
  }
  /**
   * Handle session end - sync buffered learnings
   */
  async onSessionEnd(event) {
    const sessionEvent = event;
    if (!this.config.autoLearnEnabled || this.learningBuffer.length === 0) {
      logger.debug("No learnings to sync on session end");
      return;
    }
    if (!this.isConnected) {
      const status = await this.checkStatus();
      if (!status.connected) {
        logger.warn("DiffMem not available - learnings not synced", {
          bufferedCount: this.learningBuffer.length
        });
        return;
      }
      this.isConnected = true;
    }
    try {
      await this.syncLearnings();
      const sessionDuration = Date.now() - this.sessionStartTime;
      logger.info("DiffMem session end completed", {
        learningSynced: this.learningBuffer.length,
        sessionId: sessionEvent.data.sessionId,
        sessionDurationMs: sessionDuration
      });
      this.learningBuffer = [];
    } catch (error) {
      logger.warn("DiffMem session end sync failed", {
        error: error instanceof Error ? error.message : String(error),
        bufferedCount: this.learningBuffer.length
      });
    }
  }
  /**
   * Record a learning during session
   */
  recordLearning(insight) {
    if (!this.config.autoLearnEnabled) {
      return;
    }
    if (insight.confidence < this.config.learningConfidenceThreshold) {
      logger.debug("Learning below confidence threshold", {
        confidence: insight.confidence,
        threshold: this.config.learningConfidenceThreshold
      });
      return;
    }
    const learning = {
      ...insight,
      timestamp: Date.now()
    };
    this.learningBuffer.push(learning);
    logger.debug("Learning recorded", {
      category: learning.category,
      confidence: learning.confidence,
      bufferSize: this.learningBuffer.length
    });
  }
  /**
   * Get fetched memories
   */
  getUserKnowledge() {
    return [...this.fetchedMemories];
  }
  /**
   * Format memories for LLM context with token budget
   */
  formatForContext(maxTokens = 2e3) {
    if (this.fetchedMemories.length === 0) {
      return "";
    }
    const sortedMemories = [...this.fetchedMemories].sort((a, b) => {
      if (b.confidence !== a.confidence) {
        return b.confidence - a.confidence;
      }
      return b.timestamp - a.timestamp;
    });
    const sections = /* @__PURE__ */ new Map();
    for (const memory of sortedMemories) {
      const category = memory.category;
      if (!sections.has(category)) {
        sections.set(category, []);
      }
      const categoryMemories = sections.get(category);
      if (categoryMemories) {
        categoryMemories.push(memory.content);
      }
    }
    const lines = ["## User Knowledge"];
    let estimatedTokens = 5;
    const categoryLabels = {
      preference: "Preferences",
      expertise: "Expertise",
      project_knowledge: "Project Knowledge",
      pattern: "Patterns",
      correction: "Corrections"
    };
    for (const [category, contents] of sections) {
      const label = categoryLabels[category] || category;
      const categoryHeader = `
### ${label}`;
      const headerTokens = Math.ceil(categoryHeader.length / 4);
      if (estimatedTokens + headerTokens > maxTokens) {
        break;
      }
      lines.push(categoryHeader);
      estimatedTokens += headerTokens;
      for (const content of contents) {
        const contentLine = `- ${content}`;
        const contentTokens = Math.ceil(contentLine.length / 4);
        if (estimatedTokens + contentTokens > maxTokens) {
          lines.push("- (additional items truncated for token budget)");
          break;
        }
        lines.push(contentLine);
        estimatedTokens += contentTokens;
      }
    }
    return lines.join("\n");
  }
  /**
   * Get current connection status
   */
  getStatus() {
    return {
      connected: this.isConnected,
      memoriesLoaded: this.fetchedMemories.length,
      learningsBuffered: this.learningBuffer.length
    };
  }
  /**
   * Update configuration
   */
  updateConfig(config) {
    this.config = { ...this.config, ...config };
    logger.debug("DiffMem config updated", { config: this.config });
  }
  // Private methods
  /**
   * Check DiffMem service status
   */
  async checkStatus() {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 3e3);
      const response = await fetch(`${this.config.endpoint}/status`, {
        method: "GET",
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      if (!response.ok) {
        return { connected: false, memoryCount: 0, lastSync: null };
      }
      const status = await response.json();
      return {
        connected: true,
        memoryCount: status.memoryCount || 0,
        lastSync: status.lastSync || null,
        version: status.version
      };
    } catch {
      return { connected: false, memoryCount: 0, lastSync: null };
    }
  }
  /**
   * Fetch memories from DiffMem
   */
  async fetchMemories(query) {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 5e3);
      const response = await fetch(`${this.config.endpoint}/memories/query`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(query),
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      if (!response.ok) {
        logger.warn("DiffMem query failed", { status: response.status });
        return [];
      }
      const data = await response.json();
      return data.memories || [];
    } catch (error) {
      logger.debug("DiffMem fetch failed", {
        error: error instanceof Error ? error.message : String(error)
      });
      return [];
    }
  }
  /**
   * Sync buffered learnings to DiffMem
   */
  async syncLearnings() {
    if (this.learningBuffer.length === 0) {
      return;
    }
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 1e4);
    try {
      const response = await fetch(`${this.config.endpoint}/memories/learn`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ insights: this.learningBuffer }),
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      if (!response.ok) {
        throw new Error(`Sync failed with status ${response.status}`);
      }
      logger.info("Learnings synced to DiffMem", {
        count: this.learningBuffer.length
      });
    } catch (error) {
      clearTimeout(timeoutId);
      throw error;
    }
  }
  /**
   * Inject fetched memories as frame anchors
   */
  async injectAsAnchors(sessionId) {
    if (!this.frameManager || this.fetchedMemories.length === 0) {
      return;
    }
    try {
      const byCategory = /* @__PURE__ */ new Map();
      for (const memory of this.fetchedMemories) {
        if (!byCategory.has(memory.category)) {
          byCategory.set(memory.category, []);
        }
        const categoryList = byCategory.get(memory.category);
        if (categoryList) {
          categoryList.push(memory);
        }
      }
      for (const [category, memories] of byCategory) {
        const highConfidence = memories.filter((m) => m.confidence >= 0.8);
        for (const memory of highConfidence.slice(0, 5)) {
          const anchorType = this.categoryToAnchorType(category);
          const priority = Math.round(memory.confidence * 10);
          this.frameManager.addAnchor(anchorType, memory.content, priority, {
            source: "diffmem",
            category: memory.category,
            memoryId: memory.id,
            confidence: memory.confidence,
            sessionId
          });
        }
      }
      logger.debug("Memories injected as anchors", {
        totalMemories: this.fetchedMemories.length,
        anchorsCreated: Math.min(
          this.fetchedMemories.filter((m) => m.confidence >= 0.8).length,
          25
        )
      });
    } catch (error) {
      logger.warn("Failed to inject memories as anchors", {
        error: error instanceof Error ? error.message : String(error)
      });
    }
  }
  /**
   * Map memory category to anchor type
   */
  categoryToAnchorType(category) {
    switch (category) {
      case "preference":
        return "CONSTRAINT";
      case "expertise":
        return "FACT";
      case "project_knowledge":
        return "FACT";
      case "pattern":
        return "INTERFACE_CONTRACT";
      case "correction":
        return "DECISION";
      default:
        return "FACT";
    }
  }
}
let instance = null;
function getDiffMemHooks(config) {
  if (!instance) {
    instance = new DiffMemHooks(config);
  } else if (config) {
    instance.updateConfig(config);
  }
  return instance;
}
function resetDiffMemHooks() {
  instance = null;
}
export {
  DiffMemHooks,
  getDiffMemHooks,
  resetDiffMemHooks
};
//# sourceMappingURL=diffmem-hooks.js.map
