import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import {
  createPrivacyFilter
} from "./privacy-filter.js";
import { logger } from "../monitoring/logger.js";
const DEFAULT_UNIFIED_CONTEXT_CONFIG = {
  totalTokenBudget: 8e3,
  userKnowledgeBudget: 0.2,
  // 20%
  taskContextBudget: 0.7,
  // 70%
  systemContextBudget: 0.1,
  // 10%
  privacyMode: "standard"
};
function estimateTokens(content) {
  if (!content) return 0;
  return Math.ceil(content.length / 4);
}
function truncateToTokenBudget(content, tokenBudget) {
  if (!content) return "";
  const estimatedTokens = estimateTokens(content);
  if (estimatedTokens <= tokenBudget) {
    return content;
  }
  const charLimit = tokenBudget * 4;
  const truncated = content.substring(0, charLimit);
  const lastSpace = truncated.lastIndexOf(" ");
  if (lastSpace > charLimit * 0.8) {
    return truncated.substring(0, lastSpace) + "...";
  }
  return truncated + "...";
}
class UnifiedContextAssembler {
  stackMemoryRetrieval;
  diffMemHooks;
  config;
  privacyFilter;
  constructor(stackMemoryRetrieval, diffMemHooks, config = {}) {
    this.stackMemoryRetrieval = stackMemoryRetrieval;
    this.diffMemHooks = diffMemHooks;
    this.config = { ...DEFAULT_UNIFIED_CONTEXT_CONFIG, ...config };
    this.privacyFilter = createPrivacyFilter(this.config.privacyMode);
    const totalAllocation = this.config.userKnowledgeBudget + this.config.taskContextBudget + this.config.systemContextBudget;
    if (Math.abs(totalAllocation - 1) > 1e-3) {
      logger.warn("Budget allocations do not sum to 1.0", {
        userKnowledge: this.config.userKnowledgeBudget,
        taskContext: this.config.taskContextBudget,
        systemContext: this.config.systemContextBudget,
        total: totalAllocation
      });
    }
  }
  /**
   * Assemble unified context from all sources
   */
  async assemble(query) {
    const startTime = Date.now();
    let totalPrivacyFiltered = 0;
    const userKnowledgeBudget = Math.floor(
      this.config.totalTokenBudget * this.config.userKnowledgeBudget
    );
    const taskContextBudget = Math.floor(
      this.config.totalTokenBudget * this.config.taskContextBudget
    );
    const systemContextBudget = Math.floor(
      this.config.totalTokenBudget * this.config.systemContextBudget
    );
    const {
      content: userKnowledge,
      memories: diffMemMemories,
      available: diffMemAvailable
    } = await this.gatherUserKnowledge(query, userKnowledgeBudget);
    const userKnowledgeFiltered = this.privacyFilter.filter(userKnowledge);
    totalPrivacyFiltered += userKnowledgeFiltered.redactedCount;
    const filteredUserKnowledge = truncateToTokenBudget(
      userKnowledgeFiltered.filtered,
      userKnowledgeBudget
    );
    const { content: taskContext, frameCount } = await this.gatherTaskContext(
      query,
      taskContextBudget
    );
    const taskContextFiltered = this.privacyFilter.filter(taskContext);
    totalPrivacyFiltered += taskContextFiltered.redactedCount;
    const filteredTaskContext = truncateToTokenBudget(
      taskContextFiltered.filtered,
      taskContextBudget
    );
    const systemContext = this.gatherSystemContext(systemContextBudget);
    const systemContextFiltered = this.privacyFilter.filter(systemContext);
    totalPrivacyFiltered += systemContextFiltered.redactedCount;
    const filteredSystemContext = truncateToTokenBudget(
      systemContextFiltered.filtered,
      systemContextBudget
    );
    const combined = this.combineContextSections(
      filteredUserKnowledge,
      filteredTaskContext,
      filteredSystemContext
    );
    const tokenUsage = {
      userKnowledge: estimateTokens(filteredUserKnowledge),
      taskContext: estimateTokens(filteredTaskContext),
      systemContext: estimateTokens(filteredSystemContext),
      total: estimateTokens(combined),
      budget: this.config.totalTokenBudget
    };
    const metadata = {
      diffMemAvailable,
      diffMemMemories,
      stackMemoryFrames: frameCount,
      privacyFiltered: totalPrivacyFiltered
    };
    logger.info("Unified context assembled", {
      query: query.substring(0, 50),
      tokenUsage,
      metadata,
      assemblyTimeMs: Date.now() - startTime
    });
    return {
      userKnowledge: filteredUserKnowledge,
      taskContext: filteredTaskContext,
      systemContext: filteredSystemContext,
      combined,
      tokenUsage,
      metadata
    };
  }
  /**
   * Gather user knowledge from DiffMem
   */
  async gatherUserKnowledge(query, tokenBudget) {
    if (!this.diffMemHooks) {
      return { content: "", memories: 0, available: false };
    }
    try {
      const status = await this.diffMemHooks.getStatus();
      if (!status.connected) {
        logger.debug("DiffMem not connected");
        return { content: "", memories: 0, available: false };
      }
      const memories = await this.diffMemHooks.getRelevantMemories(query, 10);
      if (memories.length === 0) {
        return { content: "", memories: 0, available: true };
      }
      const sections = ["## User Knowledge"];
      const byCategory = /* @__PURE__ */ new Map();
      for (const memory of memories) {
        const existing = byCategory.get(memory.category) || [];
        existing.push(memory);
        byCategory.set(memory.category, existing);
      }
      for (const [category, categoryMemories] of byCategory) {
        sections.push(`
### ${this.formatCategory(category)}`);
        for (const memory of categoryMemories) {
          const confidence = memory.confidence >= 0.8 ? "(high confidence)" : memory.confidence >= 0.5 ? "" : "(tentative)";
          sections.push(`- ${memory.content} ${confidence}`);
        }
      }
      const content = sections.join("\n");
      return {
        content: truncateToTokenBudget(content, tokenBudget),
        memories: memories.length,
        available: true
      };
    } catch (error) {
      logger.warn("Failed to gather user knowledge from DiffMem", { error });
      return { content: "", memories: 0, available: false };
    }
  }
  /**
   * Format category name for display
   */
  formatCategory(category) {
    return category.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
  }
  /**
   * Gather task context from StackMemory
   */
  async gatherTaskContext(query, tokenBudget) {
    try {
      const retrievedContext = await this.stackMemoryRetrieval.retrieveContext(
        query,
        {
          tokenBudget
        }
      );
      return {
        content: retrievedContext.context,
        frameCount: retrievedContext.frames.length
      };
    } catch (error) {
      logger.warn("Failed to gather task context from StackMemory", { error });
      return { content: "", frameCount: 0 };
    }
  }
  /**
   * Gather system context (environment, timestamps, etc.)
   */
  gatherSystemContext(tokenBudget) {
    const sections = ["## System Context"];
    sections.push(`
**Current Time**: ${(/* @__PURE__ */ new Date()).toISOString()}`);
    const nodeEnv = process.env.NODE_ENV || "development";
    sections.push(`**Environment**: ${nodeEnv}`);
    const projectId = process.env.STACKMEMORY_PROJECT_ID;
    if (projectId) {
      sections.push(`**Project**: ${projectId}`);
    }
    const sessionId = process.env.STACKMEMORY_SESSION_ID;
    if (sessionId) {
      sections.push(`**Session**: ${sessionId.substring(0, 8)}...`);
    }
    const content = sections.join("\n");
    return truncateToTokenBudget(content, tokenBudget);
  }
  /**
   * Combine all context sections into a single string
   */
  combineContextSections(userKnowledge, taskContext, systemContext) {
    const sections = [];
    if (taskContext) {
      sections.push(taskContext);
    }
    if (userKnowledge) {
      sections.push(userKnowledge);
    }
    if (systemContext) {
      sections.push(systemContext);
    }
    return sections.join("\n\n---\n\n");
  }
  /**
   * Update privacy mode
   */
  setPrivacyMode(mode) {
    this.config.privacyMode = mode;
    this.privacyFilter.setMode(mode);
  }
  /**
   * Get current configuration
   */
  getConfig() {
    return { ...this.config };
  }
  /**
   * Update configuration
   */
  updateConfig(config) {
    this.config = { ...this.config, ...config };
    if (config.privacyMode) {
      this.privacyFilter.setMode(config.privacyMode);
    }
  }
}
function createUnifiedContextAssembler(stackMemoryRetrieval, diffMemHooks = null, config = {}) {
  return new UnifiedContextAssembler(
    stackMemoryRetrieval,
    diffMemHooks,
    config
  );
}
export {
  DEFAULT_UNIFIED_CONTEXT_CONFIG,
  UnifiedContextAssembler,
  createUnifiedContextAssembler
};
//# sourceMappingURL=unified-context-assembler.js.map
