import {
  BoxBuilder
} from "./chunk-URB2WSKZ.js";
import {
  countRecallTokenOverlap,
  normalizeRecallTokens
} from "./chunk-DT5TVLJE.js";
import {
  StorageManager
} from "./chunk-MCC6KDQF.js";
import {
  getCachedEpisodeMap,
  setCachedEpisodeMap
} from "./chunk-PFV5C235.js";

// src/verified-recall.ts
function createReadOnlyBoxBuilder(memoryDir) {
  return new BoxBuilder(memoryDir, {
    memoryBoxesEnabled: true,
    traceWeaverEnabled: false,
    boxTopicShiftThreshold: 0.35,
    boxTimeGapMs: 30 * 60 * 1e3,
    boxMaxMemories: 50,
    traceWeaverLookbackDays: 7,
    traceWeaverOverlapThreshold: 0.4
  });
}
function scoreVerifiedEpisodeCandidate(box, verifiedMemories, queryTokens) {
  const matchedFields = /* @__PURE__ */ new Set();
  let score = 0;
  const topicMatches = countRecallTokenOverlap(queryTokens, box.topics.join(" "));
  if (topicMatches > 0) {
    score += topicMatches * 3;
    matchedFields.add("topics");
  }
  const goalMatches = countRecallTokenOverlap(queryTokens, box.goal);
  if (goalMatches > 0) {
    score += goalMatches * 4;
    matchedFields.add("goal");
  }
  const toolMatches = countRecallTokenOverlap(queryTokens, box.toolsUsed?.join(" "));
  if (toolMatches > 0) {
    score += toolMatches * 2;
    matchedFields.add("toolsUsed");
  }
  let episodeContentMatches = 0;
  for (const memory of verifiedMemories) {
    episodeContentMatches += countRecallTokenOverlap(queryTokens, memory.content);
  }
  if (episodeContentMatches > 0) {
    score += episodeContentMatches * 4;
    matchedFields.add("episodeContent");
  }
  return { score, matchedFields };
}
function resolveVerifiedEpisodeMemoriesFromMap(memoryById, memoryIds) {
  const verified = [];
  for (const memoryId of memoryIds) {
    try {
      const memory = memoryById.get(memoryId);
      if (!memory) continue;
      if (memory.frontmatter.status === "archived" || memory.frontmatter.status === "forgotten") continue;
      if (memory.frontmatter.memoryKind !== "episode") continue;
      verified.push(memory);
    } catch {
    }
  }
  return verified;
}
async function searchVerifiedEpisodes(options) {
  const queryTokens = new Set(normalizeRecallTokens(options.query, ["what", "which"]));
  if (queryTokens.size === 0 || options.maxResults <= 0) return [];
  const storage = new StorageManager(options.memoryDir);
  const version = storage.getMemoryStatusVersion();
  let verifiedMemoryById = getCachedEpisodeMap(storage.dir, version);
  if (!verifiedMemoryById) {
    const allMemories = await storage.readAllMemories();
    verifiedMemoryById = setCachedEpisodeMap(storage.dir, allMemories, version);
  }
  const boxes = await createReadOnlyBoxBuilder(options.memoryDir).readRecentBoxes(Math.max(1, Math.floor(options.boxRecallDays ?? 3))).catch(() => []);
  const candidates = [];
  for (const box of boxes) {
    const verifiedMemories = resolveVerifiedEpisodeMemoriesFromMap(verifiedMemoryById, box.memoryIds);
    if (verifiedMemories.length === 0) continue;
    const { score, matchedFields } = scoreVerifiedEpisodeCandidate(box, verifiedMemories, queryTokens);
    if (score <= 0) continue;
    candidates.push({
      box,
      score,
      matchedFields,
      verifiedMemories
    });
  }
  return candidates.map((candidate) => ({
    box: candidate.box,
    score: candidate.score,
    verifiedEpisodeCount: candidate.verifiedMemories.length,
    verifiedMemoryIds: candidate.verifiedMemories.map((memory) => memory.frontmatter.id),
    matchedFields: [...candidate.matchedFields].sort()
  })).sort(
    (left, right) => right.score - left.score || right.verifiedEpisodeCount - left.verifiedEpisodeCount || right.box.sealedAt.localeCompare(left.box.sealedAt)
  ).slice(0, options.maxResults);
}

export {
  searchVerifiedEpisodes
};
//# sourceMappingURL=chunk-RXTFCYQF.js.map