UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

90 lines (89 loc) 3.85 kB
import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js"; import { r as isPathInside } from "./path-guards-Cp-mGr3-.js"; import path from "node:path"; //#region src/shared/avatar-limits.ts /** Maximum avatar payload size accepted by local file and Gateway upload paths. */ const AVATAR_MAX_BYTES = 2097152; /** Maximum encoded length of a supported local avatar at AVATAR_MAX_BYTES. */ const AVATAR_MAX_DATA_URL_CHARS = Math.ceil(AVATAR_MAX_BYTES / 3) * 4 + 26; const AVATAR_IMAGE_DATA_URL_RE = /^data:image\//i; /** Avatar images render only as <img>; preserve the existing image/* data URL contract. */ function isAvatarImageMimeType(value) { return /^image\//i.test(value); } /** Accepts image data URLs that fit the Gateway and Control UI payload boundary. */ function isRenderableAvatarImageDataUrl(value) { return value.length <= AVATAR_MAX_DATA_URL_CHARS && AVATAR_IMAGE_DATA_URL_RE.test(value); } //#endregion //#region src/shared/avatar-policy.ts /** * Shared avatar source policy for config validation, agent identity loading, * gateway uploads, and Control UI rendering hints. */ const LOCAL_AVATAR_EXTENSIONS = /* @__PURE__ */ new Set([ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg" ]); /** MIME hints for known image extensions, including formats not accepted for local serving. */ const AVATAR_MIME_BY_EXT = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".gif": "image/gif", ".svg": "image/svg+xml", ".bmp": "image/bmp", ".tif": "image/tiff", ".tiff": "image/tiff" }; /** Detects data URLs before image-specific avatar validation. */ const AVATAR_DATA_RE = /^data:/i; /** Detects remote avatar URLs served over HTTP(S). */ const AVATAR_HTTP_RE = /^https?:\/\//i; /** Detects URI schemes so non-path avatar values can be rejected or routed. */ const AVATAR_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i; /** Detects Windows absolute paths before URI-scheme classification. */ const WINDOWS_ABS_RE = /^[a-zA-Z]:[\\/]/; const AVATAR_PATH_EXT_RE = /\.(png|jpe?g|gif|webp|svg|ico)$/i; /** Resolves a local avatar file MIME type from its extension. */ function resolveAvatarMime(filePath) { const ext = normalizeLowercaseStringOrEmpty(path.extname(filePath)); return AVATAR_MIME_BY_EXT[ext] ?? "application/octet-stream"; } /** Detects any data URL value before image-specific validation. */ function isAvatarDataUrl(value) { return AVATAR_DATA_RE.test(value); } /** Detects remote HTTP(S) avatar URLs. */ function isAvatarHttpUrl(value) { return AVATAR_HTTP_RE.test(value); } /** Detects URI-scheme-like avatar values, including non-HTTP schemes. */ function hasAvatarUriScheme(value) { return AVATAR_SCHEME_RE.test(value); } /** Detects Windows absolute paths so they are not mistaken for URI schemes. */ function isWindowsAbsolutePath(value) { return WINDOWS_ABS_RE.test(value); } /** Checks that a resolved avatar path remains inside its configured root. */ function isPathWithinRoot(rootDir, targetPath) { return isPathInside(rootDir, targetPath); } /** Heuristically detects strings that look like local avatar file paths. */ function looksLikeAvatarPath(value) { if (/[\\/]/.test(value)) return true; return AVATAR_PATH_EXT_RE.test(value); } /** Restricts local avatar files to image extensions that can be safely served inline. */ function isSupportedLocalAvatarExtension(filePath) { const ext = normalizeLowercaseStringOrEmpty(path.extname(filePath)); return LOCAL_AVATAR_EXTENSIONS.has(ext); } //#endregion export { isSupportedLocalAvatarExtension as a, resolveAvatarMime as c, isAvatarImageMimeType as d, isRenderableAvatarImageDataUrl as f, isPathWithinRoot as i, AVATAR_MAX_BYTES as l, isAvatarDataUrl as n, isWindowsAbsolutePath as o, isAvatarHttpUrl as r, looksLikeAvatarPath as s, hasAvatarUriScheme as t, AVATAR_MAX_DATA_URL_CHARS as u };