UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

33 lines (32 loc) 1.54 kB
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 = { "<": "&lt;", ">": "&gt;", "&": "&amp;", "\"": "&quot;", "'": "&apos;" }; function xmlEscapeAttr(value) { return value.replace(/[<>&"']/g, (char) => XML_ESCAPE_MAP[char] ?? char); } function escapeFileBlockContent(value) { return value.replace(/<\s*\/\s*file\s*>/gi, "&lt;/file&gt;").replace(/<\s*file\b/gi, "&lt;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 };