// src/citations.ts
var OPEN_TAG = "<oai-mem-citation>";
var CLOSE_TAG = "</oai-mem-citation>";
var ENTRIES_OPEN = "<citation_entries>";
var ENTRIES_CLOSE = "</citation_entries>";
var ROLLOUT_OPEN = "<rollout_ids>";
var ROLLOUT_CLOSE = "</rollout_ids>";
var THREAD_OPEN = "<thread_ids>";
var THREAD_CLOSE = "</thread_ids>";
function parseOaiMemCitation(text) {
  const openIdx = text.indexOf(OPEN_TAG);
  if (openIdx < 0) return null;
  const closeIdx = text.indexOf(CLOSE_TAG, openIdx + OPEN_TAG.length);
  if (closeIdx < 0) return null;
  const inner = text.slice(openIdx + OPEN_TAG.length, closeIdx);
  const entries = parseEntries(inner);
  const rolloutIds = parseIds(inner, ROLLOUT_OPEN, ROLLOUT_CLOSE) ?? parseIds(inner, THREAD_OPEN, THREAD_CLOSE) ?? [];
  if (entries.length === 0 && rolloutIds.length === 0) return null;
  return { entries, rolloutIds };
}
function parseEntries(block) {
  const start = block.indexOf(ENTRIES_OPEN);
  if (start < 0) return [];
  const end = block.indexOf(ENTRIES_CLOSE, start + ENTRIES_OPEN.length);
  if (end < 0) return [];
  const raw = block.slice(start + ENTRIES_OPEN.length, end);
  const lines = raw.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
  const results = [];
  for (const line of lines) {
    const parsed = parseEntryLine(line);
    if (parsed) results.push(parsed);
  }
  return results;
}
function parseEntryLine(line) {
  const match = line.match(/^(.+):(\d+)-(\d+)\|note=\[(.*)?\]$/);
  if (!match) return null;
  const [, pathRaw, startRaw, endRaw, noteRaw] = match;
  if (!pathRaw || !startRaw || !endRaw) return null;
  const lineStart = parseInt(startRaw, 10);
  const lineEnd = parseInt(endRaw, 10);
  if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) return null;
  if (lineStart < 0 || lineEnd < 0) return null;
  return {
    path: pathRaw.trim(),
    lineStart,
    lineEnd,
    note: noteRaw ?? ""
  };
}
function parseIds(block, openTag, closeTag) {
  const start = block.indexOf(openTag);
  if (start < 0) return null;
  const end = block.indexOf(closeTag, start + openTag.length);
  if (end < 0) return null;
  const raw = block.slice(start + openTag.length, end);
  const lines = raw.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
  const seen = /* @__PURE__ */ new Set();
  const unique = [];
  for (const id of lines) {
    if (!seen.has(id)) {
      seen.add(id);
      unique.push(id);
    }
  }
  return unique.length > 0 ? unique : null;
}
function sanitizeNoteForCitation(note) {
  return note.replace(/[\r\n]+/g, " ").trim();
}
function formatOaiMemCitation(block) {
  const entryLines = block.entries.map((e) => `${e.path}:${e.lineStart}-${e.lineEnd}|note=[${sanitizeNoteForCitation(e.note)}]`).join("\n");
  const idLines = block.rolloutIds.join("\n");
  return [
    OPEN_TAG,
    ENTRIES_OPEN,
    entryLines,
    ENTRIES_CLOSE,
    ROLLOUT_OPEN,
    idLines,
    ROLLOUT_CLOSE,
    CLOSE_TAG
  ].join("\n");
}
function buildCitationGuidance(citations) {
  if (citations.length === 0) return "";
  const entryExamples = citations.map(
    (c) => `${c.path}:${c.lineStart}-${c.lineEnd}|note=[${sanitizeNoteForCitation(c.noteDefault)}]`
  );
  const rolloutExamples = citations.filter((c) => c.rolloutId != null).map((c) => c.rolloutId);
  const seenRollouts = /* @__PURE__ */ new Set();
  const uniqueRollouts = [];
  for (const id of rolloutExamples) {
    if (!seenRollouts.has(id)) {
      seenRollouts.add(id);
      uniqueRollouts.push(id);
    }
  }
  const lines = [
    "",
    "[Remnic citation guidance]",
    "If you used any of the memories above, append the following to the END of your final reply:",
    OPEN_TAG,
    ENTRIES_OPEN,
    ...entryExamples,
    ENTRIES_CLOSE,
    ROLLOUT_OPEN,
    ...uniqueRollouts,
    ROLLOUT_CLOSE,
    CLOSE_TAG
  ];
  return lines.join("\n");
}

export {
  parseOaiMemCitation,
  sanitizeNoteForCitation,
  formatOaiMemCitation,
  buildCitationGuidance
};
//# sourceMappingURL=chunk-IQT3XTKW.js.map