const STOP_WORDS = /* @__PURE__ */ new Set([
  "what",
  "how",
  "why",
  "when",
  "where",
  "which",
  "who",
  "whose",
  "is",
  "are",
  "was",
  "were",
  "be",
  "been",
  "being",
  "the",
  "a",
  "an",
  "and",
  "or",
  "but",
  "so",
  "in",
  "on",
  "of",
  "for",
  "to",
  "by",
  "as",
  "at",
  "from",
  "with",
  "about",
  "do",
  "does",
  "did",
  "can",
  "could",
  "should",
  "would",
  "will",
  "shall",
  "may",
  "might",
  "best",
  "top",
  "good",
  "better",
  "worst",
  "between",
  "among",
  "across",
  "tradeoffs",
  "tradeoff",
  "comparison",
  "overview",
  "guide",
  "tutorial"
]);
const ENTITY_TOKEN = /^[A-Z][A-Za-z0-9]+$|^[A-Z][A-Z0-9]+$/;
const QUOTED_PHRASE = /["“]([^"”]{2,80})["”]/g;
function normaliseToken(raw) {
  return raw.replace(/^[^A-Za-z0-9]+|[^A-Za-z0-9]+$/g, "");
}
function extractNamedEntities(input) {
  if (!input) return [];
  const seen = /* @__PURE__ */ new Map();
  for (const match of input.matchAll(QUOTED_PHRASE)) {
    const phrase = match[1].trim();
    if (!phrase) continue;
    const key = phrase.toLowerCase();
    if (!seen.has(key)) seen.set(key, phrase);
  }
  for (const rawToken of input.split(/[\s,;:.!?()\[\]{}\-]+/)) {
    const token = normaliseToken(rawToken);
    if (!token) continue;
    if (STOP_WORDS.has(token.toLowerCase())) continue;
    if (!ENTITY_TOKEN.test(token)) continue;
    const key = token.toLowerCase();
    if (!seen.has(key)) seen.set(key, token);
  }
  return [...seen.values()];
}
function detectEntityGaps(question, subQueries) {
  const entities = extractNamedEntities(question);
  if (entities.length === 0) return [];
  const haystack = subQueries.join(" \n ").toLowerCase();
  const gaps = [];
  for (const entity of entities) {
    if (!haystack.includes(entity.toLowerCase())) {
      gaps.push({ entity, reason: "no sub-query planned" });
    }
  }
  return gaps;
}
export {
  detectEntityGaps,
  extractNamedEntities
};
//# sourceMappingURL=entity-extractor.js.map