// src/source-attribution.ts
var DEFAULT_CITATION_FORMAT = "[Source: agent={agent}, session={sessionId}, ts={ts}]";
var CITATION_UNKNOWN = "unknown";
function defaultCitationMatcher() {
  return /\[Source:\s*([^\]\n]+?)\]/gi;
}
function deriveSessionId(session) {
  if (!session) return void 0;
  const trimmed = session.trim();
  if (trimmed.length === 0) return void 0;
  const parts = trimmed.split(":").filter((p) => p.length > 0);
  if (parts.length === 0) return trimmed;
  return parts[parts.length - 1];
}
function formatCitation(ctx, template = DEFAULT_CITATION_FORMAT) {
  const session = ctx.session ?? "";
  const sessionId = ctx.sessionId ?? deriveSessionId(session) ?? CITATION_UNKNOWN;
  const ts = ctx.ts ?? CITATION_UNKNOWN;
  const agent = ctx.agent && ctx.agent.trim().length > 0 ? ctx.agent : CITATION_UNKNOWN;
  const date = ts && ts !== CITATION_UNKNOWN ? ts.slice(0, 10) : CITATION_UNKNOWN;
  const sessionForTemplate = session.trim().length > 0 ? session : CITATION_UNKNOWN;
  const values = {
    agent,
    session: sessionForTemplate,
    sessionId,
    ts,
    date
  };
  return template.replace(/\{([a-zA-Z_][\w]*)\}/g, (match, name) => {
    return Object.prototype.hasOwnProperty.call(values, name) ? values[name] : match;
  });
}
function hasCitation(text) {
  if (typeof text !== "string" || text.length === 0) return false;
  return defaultCitationMatcher().test(text);
}
function escapeRegExp(s) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function escapeRegExpCharClass(ch) {
  if (ch === "]") return "\\]";
  if (ch === "\\") return "\\\\";
  if (ch === "^") return "\\^";
  if (ch === "-") return "\\-";
  return escapeRegExp(ch);
}
function buildTokenPattern(nonWordSepChars) {
  const base = "\\n\\s";
  if (nonWordSepChars.size === 0) {
    return `[^\\n]+?`;
  }
  const escaped = [...nonWordSepChars].map(escapeRegExpCharClass).join("");
  return `[^${base}${escaped}]+?`;
}
var PLACEHOLDER_REGEX = /\{[a-zA-Z_][\w]*\}/g;
function templateMatcher(template) {
  const parts = template.split(PLACEHOLDER_REGEX);
  if (parts.length <= 1) return null;
  const prefix = parts[0] ?? "";
  const suffix = parts[parts.length - 1] ?? "";
  if (prefix.length > 0 || suffix.length > 0) {
    const escapedPrefix = escapeRegExp(prefix);
    const escapedSuffix = escapeRegExp(suffix);
    const innerParts = parts.slice(1, -1);
    const nonWordSepChars = /* @__PURE__ */ new Set();
    for (const sep of innerParts) {
      for (const ch of sep) {
        if (!/\w/.test(ch)) {
          nonWordSepChars.add(ch);
        }
      }
    }
    const interToken = buildTokenPattern(nonWordSepChars);
    const lastToken = buildTokenPattern(/* @__PURE__ */ new Set());
    const middle = innerParts.length === 0 ? lastToken : interToken + innerParts.slice(0, -1).map((sep) => escapeRegExp(sep) + interToken).join("") + escapeRegExp(innerParts[innerParts.length - 1]) + lastToken;
    const pattern = escapedPrefix + middle + escapedSuffix;
    return new RegExp(pattern, "i");
  }
  const middleLiterals = parts.slice(1, -1);
  const hasNonEmptyMiddle = middleLiterals.some((p) => p.length > 0);
  if (!hasNonEmptyMiddle) {
    return null;
  }
  const idToken = "[\\w.:-]+";
  const body = idToken + middleLiterals.map((lit) => escapeRegExp(lit) + idToken).join("");
  const separatorText = middleLiterals.join("");
  if (/\s/.test(separatorText)) {
    const opener = "[\\[\\(\\<]";
    const closer = "[\\]\\)\\>]";
    return new RegExp(opener + body + closer, "i");
  }
  const leadAnchor = "(?:(?<=[\\[\\(\\<])|(?<!\\S))";
  const trailAnchor = "(?:(?=[\\]\\)\\>])|(?=\\s*$))";
  return new RegExp(leadAnchor + body + trailAnchor, "i");
}
function hasCitationForTemplate(text, template) {
  if (typeof text !== "string" || text.length === 0) return false;
  if (hasCitation(text)) return true;
  if (template === DEFAULT_CITATION_FORMAT) return false;
  if (!PLACEHOLDER_REGEX.test(template)) {
    PLACEHOLDER_REGEX.lastIndex = 0;
    return text.includes(template);
  }
  PLACEHOLDER_REGEX.lastIndex = 0;
  const matcher = templateMatcher(template);
  if (!matcher) {
    return false;
  }
  return matcher.test(text);
}
function attachCitation(text, ctx, template = DEFAULT_CITATION_FORMAT) {
  if (typeof text !== "string") return text;
  if (hasCitationForTemplate(text, template)) return text;
  const trimmedEnd = text.replace(/\s+$/u, "");
  if (trimmedEnd.length === 0) return text;
  const citation = formatCitation(ctx, template);
  const trailing = text.slice(trimmedEnd.length);
  return `${trimmedEnd} ${citation}${trailing}`;
}
function parseCitation(text) {
  if (typeof text !== "string" || text.length === 0) return null;
  const matcher = defaultCitationMatcher();
  const match = matcher.exec(text);
  if (!match) return null;
  const body = match[1] ?? "";
  const raw = match[0] ?? "";
  const parsed = { raw };
  const fields = body.split(",").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
  for (const field of fields) {
    const eqIdx = field.indexOf("=");
    if (eqIdx <= 0) continue;
    const key = field.slice(0, eqIdx).trim().toLowerCase();
    const value = field.slice(eqIdx + 1).trim();
    if (value.length === 0) continue;
    switch (key) {
      case "agent":
        parsed.agent = value;
        break;
      case "session":
      case "sessionid":
        parsed.session = value;
        break;
      case "ts":
      case "timestamp":
        parsed.ts = value;
        break;
      default:
        break;
    }
  }
  return parsed;
}
function parseAllCitations(text) {
  if (typeof text !== "string" || text.length === 0) return [];
  const matcher = defaultCitationMatcher();
  const results = [];
  let match;
  while ((match = matcher.exec(text)) !== null) {
    const parsed = parseCitation(match[0]);
    if (parsed) results.push(parsed);
  }
  return results;
}
function stripCitation(text) {
  if (typeof text !== "string" || text.length === 0) return text;
  if (!hasCitation(text)) return text;
  const matcher = defaultCitationMatcher();
  let result = "";
  let lastIndex = 0;
  let match;
  while ((match = matcher.exec(text)) !== null) {
    const before = text.slice(lastIndex, match.index).replace(/[ \t]+$/, "");
    result += before;
    lastIndex = match.index + match[0].length;
  }
  const after = text.slice(lastIndex).replace(/^[ \t]+/, "");
  if (after.length > 0) {
    if (result.length > 0) result += " ";
    result += after;
  }
  return result.trimEnd();
}
function stripCitationForTemplate(text, template) {
  if (typeof text !== "string" || text.length === 0) return text;
  if (hasCitation(text)) return stripCitation(text);
  if (!hasCitationForTemplate(text, template)) return text;
  const matcher = templateMatcher(template);
  if (!matcher) return stripCitation(text);
  const globalMatcher = new RegExp(
    matcher.source,
    matcher.flags.includes("g") ? matcher.flags : matcher.flags + "g"
  );
  let result = "";
  let lastIndex = 0;
  let match;
  while ((match = globalMatcher.exec(text)) !== null) {
    const before = text.slice(lastIndex, match.index).replace(/[ \t]+$/, "");
    result += before;
    lastIndex = match.index + match[0].length;
    if (match[0].length === 0) {
      globalMatcher.lastIndex++;
    }
  }
  const after = text.slice(lastIndex).replace(/^[ \t]+/, "");
  if (after.length > 0) {
    if (result.length > 0) result += " ";
    result += after;
  }
  return result.trimEnd();
}

export {
  DEFAULT_CITATION_FORMAT,
  CITATION_UNKNOWN,
  deriveSessionId,
  formatCitation,
  hasCitation,
  hasCitationForTemplate,
  attachCitation,
  parseCitation,
  parseAllCitations,
  stripCitation,
  stripCitationForTemplate
};
//# sourceMappingURL=chunk-NN2DKE4T.js.map