import {
  collectNativeKnowledgeChunks
} from "./chunk-7SEAZFFB.js";
import {
  compareEntityTimestamps,
  normalizeEntityName
} from "./chunk-MCC6KDQF.js";
import {
  sanitizeMemoryContent
} from "./chunk-FVQJYWH7.js";
import {
  normalizeEntityText,
  resolveRequestedEntitySectionKeys
} from "./chunk-4DJQYKMN.js";

// src/entity-retrieval.ts
import { createHash } from "crypto";
import { mkdir, readFile, writeFile } from "fs/promises";
import path from "path";
var ENTITY_INDEX_VERSION = 3;
var RECENT_TRANSCRIPT_LOOKBACK_HOURS = 24;
var INSTRUCTION_LIKE_RE = /\b(always|never|must|should|remember to|do not|don't|process|workflow|template|checklist|instruction)\b/i;
var METADATA_WRAPPER_RE = /^(source|context|metadata|notes?):/i;
var ENTITY_PRONOUN_RE = /\b(he|him|his|she|her|they|them|their|it|its)\b/i;
function tokenize(value) {
  return normalizeEntityText(value).split(/\s+/).filter((token) => token.length >= 2);
}
function uniqueStrings(values) {
  return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
}
function containsPhrase(haystack, needle) {
  if (!needle) return false;
  const escaped = needle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  return new RegExp(`(^|\\b)${escaped}(\\b|$)`, "i").test(haystack);
}
function compactLine(value, maxLength = 220) {
  const normalized = value.replace(/\s+/g, " ").trim();
  if (normalized.length <= maxLength) return normalized;
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}\u2026`;
}
function dedupeHintSnippetsByText(snippets) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const snippet of snippets) {
    const key = normalizeEntityText(snippet.text);
    if (seen.has(key)) continue;
    seen.add(key);
    result.push(snippet);
  }
  return result;
}
function relationLine(entry, relationship) {
  const normalizedLabel = relationship.label.replace(/\s+/g, " ").trim();
  if (normalizedLabel.length === 0) return `${entry.name} is connected to ${relationship.target}`;
  return `${entry.name} ${normalizedLabel} ${relationship.target}`;
}
function detectEntityQueryMode(query) {
  const normalized = normalizeEntityText(query);
  if (!normalized) return null;
  if (/^(what about|and what about|how about|what happened (with|to) (he|him|his|she|her|they|them|their|it|its)|did (he|she|they|it)|is (he|she|they|it)|was (he|she|they|it))\b/.test(normalized)) {
    return "follow_up";
  }
  if (/^(who is|who s|what do we know about|what does|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\b/.test(normalized)) {
    if (/^what does\b/.test(normalized)) {
      if (/^what does (?:this|that|it|the|a|an|my|our|your|their)\b/.test(normalized)) {
        return null;
      }
      if (/^what does [a-z0-9-]+ (?:error|warning|exception|failure|stack|trace|code|message|log)\b/.test(normalized) && /\b(mean|means|indicate|indicates|imply|implies)\b/.test(normalized)) {
        return null;
      }
    }
    return /what happened|what s new|status of|how is|where is/.test(normalized) ? "timeline" : "direct";
  }
  if (ENTITY_PRONOUN_RE.test(normalized) && normalized.split(/\s+/).length <= 8) {
    return "follow_up";
  }
  return null;
}
function scoreAliasMatch(query, alias) {
  const normalizedQuery = normalizeEntityText(query);
  const normalizedAlias = normalizeEntityText(alias);
  if (!normalizedAlias) return 0;
  if (normalizedQuery === normalizedAlias) return 10;
  if (containsPhrase(normalizedQuery, normalizedAlias)) return 8 + Math.min(normalizedAlias.split(/\s+/).length, 3);
  const queryTokens = new Set(tokenize(normalizedQuery));
  const aliasTokens = tokenize(normalizedAlias);
  if (aliasTokens.length === 0) return 0;
  const overlap = aliasTokens.filter((token) => queryTokens.has(token)).length;
  if (overlap === 0) return 0;
  if (aliasTokens.length > 1) {
    const nonAffixOverlap = aliasTokens.filter(
      (token) => queryTokens.has(token) && !isAliasAffixToken(token)
    ).length;
    if (nonAffixOverlap === 0) return 0;
  }
  return overlap;
}
var ALIAS_AFFIX_TOKENS = /* @__PURE__ */ new Set([
  "person",
  "people",
  "user",
  "users",
  "team",
  "teams",
  "project",
  "projects",
  "topic",
  "topics",
  "org",
  "orgs",
  "organization",
  "organizations",
  "company",
  "companies",
  "place",
  "places",
  "tool",
  "tools",
  "service",
  "services",
  "system",
  "systems",
  "agent",
  "agents",
  "bot",
  "bots"
]);
function isAliasAffixToken(token) {
  return ALIAS_AFFIX_TOKENS.has(token);
}
function isLikelyInstructionLike(value) {
  return INSTRUCTION_LIKE_RE.test(value) || METADATA_WRAPPER_RE.test(value);
}
function sanitizeEntityFact(fact) {
  const sanitized = sanitizeMemoryContent(fact);
  const clean = sanitized.text.trim();
  if (!clean) return "";
  if (INSTRUCTION_LIKE_RE.test(clean) && clean.length > 100) return "";
  return clean;
}
function scoreHintSnippet(snippet, queryTokens) {
  const normalized = normalizeEntityText(snippet.text);
  if (!normalized) return null;
  const scored = { ...snippet };
  if (isLikelyInstructionLike(scored.text) && scored.kind !== "summary") {
    scored.score -= 3;
  }
  const overlap = queryTokens.filter((token) => normalized.includes(token)).length;
  scored.score += overlap * 2;
  if (METADATA_WRAPPER_RE.test(scored.text)) scored.score -= 2;
  if (scored.text.length <= 160) scored.score += 1;
  return scored.score > 0 ? scored : null;
}
function sortTimelineEntriesDesc(left, right) {
  const timestampOrder = compareEntityTimestamps(right.timestamp, left.timestamp);
  if (timestampOrder !== 0) {
    return timestampOrder;
  }
  return right.text.localeCompare(left.text);
}
function jaccardSimilarity(a, b) {
  const aTokens = new Set(tokenize(a));
  const bTokens = new Set(tokenize(b));
  if (aTokens.size === 0 || bTokens.size === 0) return 0;
  let intersection = 0;
  for (const token of aTokens) {
    if (bTokens.has(token)) intersection += 1;
  }
  const union = (/* @__PURE__ */ new Set([...aTokens, ...bTokens])).size;
  return union === 0 ? 0 : intersection / union;
}
function buildAliasIndex(entries) {
  const index = /* @__PURE__ */ new Map();
  for (const entry of entries) {
    const aliases = uniqueStrings([entry.name, ...entry.aliases]).map(normalizeEntityText).filter(Boolean);
    for (const alias of aliases) {
      const existing = index.get(alias) ?? [];
      existing.push(entry);
      index.set(alias, existing);
    }
  }
  return index;
}
async function readNativeChunks(config, recallNamespaces) {
  if (!config.nativeKnowledge?.enabled) return [];
  return collectNativeKnowledgeChunks({
    workspaceDir: config.workspaceDir,
    memoryDir: config.memoryDir,
    config: config.nativeKnowledge,
    recallNamespaces: config.namespacesEnabled ? recallNamespaces : void 0,
    defaultNamespace: config.defaultNamespace
  }).catch(() => []);
}
function entityIndexStatePath(storage) {
  return path.join(storage.dir, "state", "entity-mention-index.json");
}
async function readEntityIndexState(storage) {
  const raw = await readFile(entityIndexStatePath(storage), "utf-8").catch(() => "");
  if (!raw) return null;
  try {
    const parsed = JSON.parse(raw);
    if (parsed.version !== ENTITY_INDEX_VERSION || !Array.isArray(parsed.entities)) return null;
    return parsed;
  } catch {
    return null;
  }
}
async function writeEntityIndexState(storage, index) {
  const statePath = entityIndexStatePath(storage);
  await mkdir(path.dirname(statePath), { recursive: true });
  const nextContent = JSON.stringify(index, null, 2) + "\n";
  const currentContent = await readFile(statePath, "utf-8").catch(() => "");
  if (currentContent === nextContent) return;
  await writeFile(statePath, nextContent, "utf-8");
}
function nativePseudoCanonicalId(chunk) {
  return `native:${createHash("sha256").update(chunk.sourcePath).digest("hex").slice(0, 12)}`;
}
function createPseudoNativeEntry(chunk) {
  const canonicalId = nativePseudoCanonicalId(chunk);
  return {
    canonicalId,
    name: chunk.title,
    type: chunk.sourceKind,
    aliases: uniqueStrings(chunk.aliases ?? []),
    facts: [],
    structuredSections: [],
    timelineFacts: [],
    timeline: [],
    relationships: [],
    activity: [],
    factCount: 0,
    memorySnippets: [],
    nativeChunks: [
      {
        chunkId: chunk.chunkId,
        title: chunk.title,
        sourceKind: chunk.sourceKind,
        sourcePath: chunk.sourcePath,
        snippet: compactLine(chunk.content, 180),
        derivedDate: chunk.derivedDate
      }
    ]
  };
}
function mergeNativeChunk(entry, chunk) {
  const existing = entry.nativeChunks.find((item) => item.chunkId === chunk.chunkId);
  if (existing) return;
  entry.nativeChunks.push({
    chunkId: chunk.chunkId,
    title: chunk.title,
    sourceKind: chunk.sourceKind,
    sourcePath: chunk.sourcePath,
    snippet: compactLine(chunk.content, 180),
    derivedDate: chunk.derivedDate
  });
  entry.aliases = uniqueStrings([...entry.aliases, ...chunk.aliases ?? []]);
}
async function buildEntityMentionIndex(storage, config, recallNamespaces) {
  const [previousIndex, entityFiles, memories, nativeChunks] = await Promise.all([
    readEntityIndexState(storage),
    storage.readAllEntityFiles(),
    storage.readAllMemories(),
    readNativeChunks(config, recallNamespaces)
  ]);
  const entities = /* @__PURE__ */ new Map();
  for (const entity of entityFiles) {
    const canonicalId = normalizeEntityName(entity.name, entity.type);
    const sanitizedFacts = entity.facts.map((fact) => sanitizeEntityFact(fact)).filter(Boolean).map((fact) => compactLine(fact, 180));
    const sanitizedTimelineFacts = entity.timeline.map((entry) => sanitizeEntityFact(entry.text)).filter(Boolean).map((fact) => compactLine(fact, 180));
    entities.set(canonicalId, {
      canonicalId,
      name: entity.name,
      type: entity.type,
      aliases: uniqueStrings(entity.aliases),
      summary: entity.synthesis?.trim() || entity.summary?.trim() || void 0,
      facts: sanitizedFacts,
      timelineFacts: uniqueStrings(sanitizedTimelineFacts),
      structuredSections: (entity.structuredSections ?? []).map((section) => ({
        key: section.key,
        title: section.title,
        facts: section.facts.map((fact) => sanitizeEntityFact(fact)).filter(Boolean).map((fact) => compactLine(fact, 180))
      })).filter((section) => section.facts.length > 0),
      timeline: entity.timeline.map((entry) => ({ ...entry })),
      relationships: entity.relationships.map((relationship) => ({ ...relationship })),
      activity: entity.activity.map((activity) => ({ ...activity })),
      factCount: sanitizedFacts.length,
      memorySnippets: [],
      nativeChunks: []
    });
  }
  for (const memory of memories) {
    const entityRef = typeof memory.frontmatter.entityRef === "string" ? memory.frontmatter.entityRef : "";
    if (!entityRef) continue;
    const entry = entities.get(entityRef);
    if (!entry) continue;
    const snippet = await readMemorySnippet(memory);
    if (!entry.memorySnippets.includes(snippet)) {
      entry.memorySnippets.push(snippet);
    }
  }
  const aliasIndex = buildAliasIndex([...entities.values()]);
  for (const chunk of nativeChunks) {
    const existingPseudo = entities.get(nativePseudoCanonicalId(chunk));
    if (existingPseudo) {
      mergeNativeChunk(existingPseudo, chunk);
      continue;
    }
    const candidateAliases = uniqueStrings([chunk.title, ...chunk.aliases ?? []]).map(normalizeEntityText).filter(Boolean);
    let matched = false;
    for (const alias of candidateAliases) {
      for (const entry of aliasIndex.get(alias) ?? []) {
        mergeNativeChunk(entry, chunk);
        matched = true;
      }
    }
    if (matched) continue;
    const pseudoEntry = createPseudoNativeEntry(chunk);
    entities.set(pseudoEntry.canonicalId, pseudoEntry);
  }
  const sortedEntities = [...entities.values()].sort((left, right) => left.name.localeCompare(right.name));
  const previousEntities = previousIndex ? JSON.stringify(previousIndex.entities) : "";
  const nextEntities = JSON.stringify(sortedEntities);
  const index = {
    version: ENTITY_INDEX_VERSION,
    updatedAt: previousIndex && previousEntities === nextEntities ? previousIndex.updatedAt : (/* @__PURE__ */ new Date()).toISOString(),
    entities: sortedEntities
  };
  await writeEntityIndexState(storage, index);
  return index;
}
function resolveExplicitCandidates(index, query) {
  const candidates = [];
  for (const entry of index.entities) {
    const aliases = uniqueStrings([entry.name, ...entry.aliases]);
    let bestAlias = "";
    let bestScore = 0;
    for (const alias of aliases) {
      const score = scoreAliasMatch(query, alias);
      if (score > bestScore) {
        bestAlias = alias;
        bestScore = score;
      }
    }
    if (bestScore <= 0) continue;
    candidates.push({ entry, alias: bestAlias, score: bestScore, source: "query" });
  }
  return candidates.sort((left, right) => right.score - left.score);
}
function resolveRecentTurnCandidates(index, transcriptEntries, recentTurns) {
  if (recentTurns <= 0 || transcriptEntries.length === 0) return [];
  const recentEntries = transcriptEntries.slice(-recentTurns);
  const candidates = /* @__PURE__ */ new Map();
  for (let indexOffset = recentEntries.length - 1; indexOffset >= 0; indexOffset -= 1) {
    const turn = recentEntries[indexOffset];
    const recencyBoost = recentEntries.length - indexOffset;
    const roleWeight = turn.role === "user" ? 2 : turn.role === "assistant" ? -1 : 0;
    for (const entry of index.entities) {
      const aliases = uniqueStrings([entry.name, ...entry.aliases]);
      for (const alias of aliases) {
        const score = scoreAliasMatch(turn.content, alias);
        if (score <= 0) continue;
        const current = candidates.get(entry.canonicalId);
        const weightedScore = score + Math.max(0, 6 - recencyBoost) + roleWeight;
        if (!current || weightedScore > current.score) {
          candidates.set(entry.canonicalId, {
            entry,
            alias,
            score: weightedScore,
            source: "recent_turn"
          });
        }
      }
    }
  }
  return [...candidates.values()].sort((left, right) => right.score - left.score);
}
async function readMemorySnippet(memory) {
  const content = memory.content.replace(/\s+/g, " ").trim();
  return compactLine(content, 180);
}
async function buildHintSnippets(entry, queryTokens, mode, maxSupportingFacts, requestedSectionKeys) {
  const snippets = [];
  const aliasTokens = new Set(tokenize(uniqueStrings([entry.name, ...entry.aliases]).join(" ")));
  if (entry.summary) {
    snippets.push({ text: compactLine(entry.summary, 180), score: 10, kind: "summary" });
  }
  if (requestedSectionKeys.size > 0) {
    for (const section of entry.structuredSections) {
      if (!requestedSectionKeys.has(normalizeEntityText(section.key).replace(/\s+/g, "_"))) continue;
      for (const fact of section.facts) {
        snippets.push({ text: fact, score: mode === "direct" ? 8 : 9, kind: "section" });
      }
    }
  } else {
    for (const fact of entry.timelineFacts) {
      snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
    }
    for (const section of entry.structuredSections) {
      for (const fact of section.facts) {
        const normalizedFact = normalizeEntityText(fact);
        const hasNonAliasQueryOverlap = queryTokens.some(
          (token) => !aliasTokens.has(token) && normalizedFact.includes(token)
        );
        if (entry.timelineFacts.length > 0 && !hasNonAliasQueryOverlap) {
          continue;
        }
        snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
      }
    }
    if (entry.timelineFacts.length === 0 && entry.structuredSections.length === 0) {
      for (const fact of entry.facts) {
        if (!fact.trim()) continue;
        snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
      }
    }
  }
  if (requestedSectionKeys.size === 0) {
    for (const relationship of entry.relationships) {
      snippets.push({
        text: compactLine(relationLine(entry, relationship), 180),
        score: mode === "direct" && entry.type.toLowerCase() === "person" ? 6 : 4,
        kind: "relationship"
      });
    }
    for (const activity of entry.activity) {
      snippets.push({
        text: compactLine(`${activity.date}: ${activity.note}`, 180),
        score: 4,
        kind: "activity"
      });
    }
    for (const memorySnippet of entry.memorySnippets.slice(0, Math.min(maxSupportingFacts, 4))) {
      snippets.push({
        text: memorySnippet,
        score: 5,
        kind: "memory"
      });
    }
    for (const chunk of entry.nativeChunks) {
      snippets.push({
        text: compactLine(chunk.snippet, 180),
        score: 3,
        kind: "native"
      });
    }
  }
  const deduped = /* @__PURE__ */ new Map();
  for (const snippet of snippets) {
    const scored = scoreHintSnippet(snippet, queryTokens);
    if (!scored) continue;
    const normalized = normalizeEntityText(scored.text);
    const existing = deduped.get(normalized);
    if (!existing || scored.score > existing.score) deduped.set(normalized, scored);
  }
  return [...deduped.values()].filter((snippet) => snippet.score > 0).sort((left, right) => right.score - left.score).slice(0, maxSupportingFacts);
}
function summarizeUncertainty(snippets) {
  const direct = snippets.filter(
    (snippet) => snippet.kind === "summary" || snippet.kind === "fact" || snippet.kind === "section" || snippet.kind === "memory"
  );
  if (direct.length < 2) return null;
  for (let index = 0; index < direct.length; index += 1) {
    for (let compare = index + 1; compare < direct.length; compare += 1) {
      if (jaccardSimilarity(direct[index].text, direct[compare].text) < 0.2) {
        return "Evidence is mixed across stored facts; treat the hints below as partial and verify before answering definitively.";
      }
    }
  }
  return null;
}
function formatEntityHintSection(candidates, queryTokens, mode, maxRelatedEntities, maxChars) {
  if (candidates.length === 0) return null;
  const lines = ["## entity_answer_hints", ""];
  for (const { candidate, snippets, uncertainty } of candidates) {
    const hasSummary = Boolean(candidate.entry.summary?.trim());
    const preferredTopSnippets = hasSummary ? snippets.filter((snippet) => snippet.kind !== "fact") : snippets;
    let topSnippets = (preferredTopSnippets.length > 0 ? preferredTopSnippets : snippets).slice(0, 3);
    const buildTimelineSnippets = (seedExcludedTexts) => {
      const explicitTimelinePool = dedupeHintSnippetsByText(
        (candidate.entry.timeline ?? []).slice().sort(sortTimelineEntriesDesc).map((entry) => sanitizeEntityFact(entry.text)).filter(Boolean).map((text) => scoreHintSnippet({
          text: compactLine(text, 180),
          score: 7,
          kind: "activity"
        }, queryTokens)).filter((snippet) => snippet !== null).filter((snippet) => !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
      ).slice(0, 2);
      const activityTimelinePool = dedupeHintSnippetsByText(
        snippets.filter((snippet) => (snippet.kind === "activity" || snippet.kind === "memory") && !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
      ).slice(0, 2);
      return explicitTimelinePool.length > 0 ? explicitTimelinePool : activityTimelinePool.length > 0 ? activityTimelinePool : dedupeHintSnippetsByText(
        snippets.filter((snippet) => (snippet.kind === "fact" || snippet.kind === "summary") && !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
      ).slice(0, 2);
    };
    const baseTopSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));
    const timelinePool = mode !== "direct" ? buildTimelineSnippets(baseTopSnippetTexts) : [];
    if (mode !== "direct" && hasSummary && topSnippets.length < 2) {
      if (timelinePool.length > 0) {
        topSnippets = [...topSnippets, timelinePool[0]].slice(0, 3);
      }
    }
    const topSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));
    lines.push(`- target: ${candidate.entry.name} (${candidate.entry.type})`);
    if (candidate.source === "recent_turn") {
      lines.push(`- resolution: carried forward from recent turns via alias "${candidate.alias}"`);
    } else {
      lines.push(`- resolution: matched alias "${candidate.alias}" in the query`);
    }
    if (uncertainty) lines.push(`- uncertainty: ${uncertainty}`);
    if (topSnippets.length > 0) {
      lines.push("- likely answer:");
      for (const snippet of topSnippets) {
        lines.push(`  - ${snippet.text}`);
      }
    }
    if (mode !== "direct") {
      const fallbackTimeline = timelinePool.filter(
        (snippet) => !topSnippetTexts.has(normalizeEntityText(snippet.text))
      );
      if (fallbackTimeline.length > 0) {
        lines.push("- recent timeline:");
        for (const snippet of fallbackTimeline) {
          lines.push(`  - ${snippet.text}`);
        }
      }
    }
    const related = candidate.entry.relationships.slice(0, maxRelatedEntities).map((relationship) => relationship.target);
    if (related.length > 0) {
      lines.push(`- related entities: ${related.join(", ")}`);
    }
    lines.push(`- support counts: facts=${candidate.entry.factCount}, memories=${candidate.entry.memorySnippets.length}, native=${candidate.entry.nativeChunks.length}`);
    lines.push("");
  }
  let result = lines.join("\n");
  if (result.length > maxChars) {
    result = `${result.slice(0, Math.max(0, maxChars - 15)).trimEnd()}

...(trimmed)
`;
  }
  return result.trim().length > 0 ? result.trimEnd() : null;
}
async function buildEntityRecallSection(options) {
  const mode = detectEntityQueryMode(options.query);
  if (!mode) return null;
  const index = await buildEntityMentionIndex(options.storage, options.config, options.recallNamespaces);
  if (index.entities.length === 0) return null;
  const explicitCandidates = resolveExplicitCandidates(index, options.query);
  const candidates = explicitCandidates.length > 0 ? explicitCandidates : resolveRecentTurnCandidates(index, options.transcriptEntries, options.recentTurns);
  if (candidates.length === 0) return null;
  const queryTokens = tokenize(options.query);
  const candidateLimit = explicitCandidates.length === 0 && mode === "follow_up" ? 1 : options.maxHints;
  const rankedCandidates = candidates.slice(0, candidateLimit);
  const enriched = await Promise.all(
    rankedCandidates.map(async (candidate) => {
      const requestedSectionKeys = new Set(
        resolveRequestedEntitySectionKeys(
          options.query,
          candidate.entry.type,
          candidate.entry.structuredSections,
          options.config.entitySchemas
        )
      );
      const snippets = await buildHintSnippets(
        candidate.entry,
        queryTokens,
        mode,
        options.maxSupportingFacts,
        requestedSectionKeys
      );
      return {
        candidate,
        snippets,
        uncertainty: summarizeUncertainty(snippets)
      };
    })
  );
  const section = formatEntityHintSection(enriched, queryTokens, mode, options.maxRelatedEntities, options.maxChars);
  if (!section) return null;
  return section;
}
async function readRecentEntityTranscriptEntries(transcriptEntriesPromise, recentTurns) {
  if (recentTurns <= 0) return [];
  const transcriptEntries = await transcriptEntriesPromise.catch(() => []);
  if (transcriptEntries.length === 0) return [];
  return transcriptEntries.slice(-Math.max(1, recentTurns * 2));
}
var entityIndexVersion = ENTITY_INDEX_VERSION;
var entityRecentTranscriptLookbackHours = RECENT_TRANSCRIPT_LOOKBACK_HOURS;

export {
  buildEntityRecallSection,
  readRecentEntityTranscriptEntries,
  entityIndexVersion,
  entityRecentTranscriptLookbackHours
};
//# sourceMappingURL=chunk-LIO5X3CM.js.map