// src/rerank.ts
var RerankCache = class {
  entries = /* @__PURE__ */ new Map();
  get(key) {
    const e = this.entries.get(key);
    if (!e) return null;
    if (Date.now() > e.expiresAtMs) {
      this.entries.delete(key);
      return null;
    }
    return e.rankedIds;
  }
  set(key, rankedIds, ttlMs) {
    this.entries.set(key, { rankedIds, expiresAtMs: Date.now() + ttlMs });
  }
};
function parseRerankResponse(raw, candidates) {
  const byId = /* @__PURE__ */ new Map();
  for (const c of candidates) byId.set(c.id, c);
  const scores = /* @__PURE__ */ new Map();
  try {
    const parsed = JSON.parse(raw);
    if (Array.isArray(parsed.scores)) {
      for (const s of parsed.scores) {
        if (!s || typeof s.id !== "string") continue;
        if (!byId.has(s.id)) continue;
        if (typeof s.score !== "number" || !Number.isFinite(s.score)) continue;
        scores.set(s.id, s.score);
      }
    }
  } catch {
  }
  const withScore = candidates.map((c) => ({
    ...c,
    score: scores.get(c.id)
  }));
  return withScore.sort((a, b) => {
    const as = a.score;
    const bs = b.score;
    if (typeof as === "number" && typeof bs === "number") {
      if (bs !== as) return bs - as;
      return a.originalIndex - b.originalIndex;
    }
    if (typeof as === "number") return -1;
    if (typeof bs === "number") return 1;
    return a.originalIndex - b.originalIndex;
  });
}
function stableKey(query, ids) {
  return `${query.trim().toLowerCase()}|${ids.join(",")}`;
}
function clampSnippet(snippet, maxChars) {
  const s = snippet.replace(/\s+/g, " ").trim();
  return s.length > maxChars ? s.slice(0, maxChars) : s;
}
async function rerankLocalOrNoop(opts) {
  if (!opts.enabled) return null;
  const ids = opts.candidates.slice(0, opts.maxCandidates).map((c) => c.id);
  if (ids.length <= 1) return ids;
  const key = stableKey(opts.query, ids);
  if (opts.cache && opts.cacheEnabled) {
    const cached = opts.cache.get(key);
    if (cached) return cached;
  }
  const payload = opts.candidates.slice(0, opts.maxCandidates).map((c) => ({
    id: c.id,
    snippet: clampSnippet(c.snippet, 400)
  }));
  const system = "You are a ranking system. Return JSON only. No markdown, no commentary.";
  const user = JSON.stringify(
    {
      task: "rerank",
      query: opts.query,
      candidates: payload,
      output: {
        scores: [{ id: "string", score: "number 0-100" }]
      },
      rules: [
        "Assign higher score to more relevant candidates.",
        "Prefer durability and direct relevance to the query.",
        "If unsure, keep scores close together."
      ]
    },
    null,
    0
  );
  const res = await opts.local.chatCompletion(
    [
      { role: "system", content: system },
      { role: "user", content: user }
    ],
    {
      maxTokens: 800,
      temperature: 0,
      timeoutMs: opts.timeoutMs,
      operation: "rerank",
      priority: "recall-critical"
    }
  );
  if (!res?.content) return null;
  const parsed = parseRerankResponse(
    res.content,
    ids.map((id, i) => ({ id, originalIndex: i }))
  );
  const rankedIds = parsed.map((p) => p.id);
  if (opts.cache && opts.cacheEnabled) {
    opts.cache.set(key, rankedIds, opts.cacheTtlMs);
  }
  return rankedIds;
}

export {
  RerankCache,
  parseRerankResponse,
  rerankLocalOrNoop
};
//# sourceMappingURL=chunk-C7VW7C3F.js.map