openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
33 lines (32 loc) • 1.54 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { L as sanitizeUntrustedFileName } from "./fs-safe-B6pvPGnf.js";
//#region src/media/file-context.ts
const XML_ESCAPE_MAP = {
"<": "<",
">": ">",
"&": "&",
"\"": """,
"'": "'"
};
function xmlEscapeAttr(value) {
return value.replace(/[<>&"']/g, (char) => XML_ESCAPE_MAP[char] ?? char);
}
function escapeFileBlockContent(value) {
return value.replace(/<\s*\/\s*file\s*>/gi, "</file>").replace(/<\s*file\b/gi, "<file");
}
function sanitizeFileName(value, fallbackName) {
const normalized = normalizeOptionalString(typeof value === "string" ? value.replace(/[\r\n\t]+/g, " ") : void 0) ?? "";
return sanitizeUntrustedFileName(normalized, fallbackName);
}
/** Renders sanitized attachment text as a model-visible file block without allowing file-tag injection. */
function renderFileContextBlock(params) {
const fallbackName = normalizeOptionalString(params.fallbackName) ?? "attachment";
const safeName = sanitizeFileName(params.filename, fallbackName);
const safeContent = escapeFileBlockContent(params.content);
const mimeType = normalizeOptionalString(params.mimeType);
const attrs = [`name="${xmlEscapeAttr(safeName)}"`, mimeType ? `mime="${xmlEscapeAttr(mimeType)}"` : void 0].filter(Boolean).join(" ");
if (params.surroundContentWithNewlines === false) return `<file ${attrs}>${safeContent}</file>`;
return `<file ${attrs}>\n${safeContent}\n</file>`;
}
//#endregion
export { renderFileContextBlock as t };