diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUtils.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUtils.tsx index 6d327f41bf0..b36d05c10aa 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUtils.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ResponsesImageUtils.tsx @@ -21,9 +21,11 @@ export const sanitizeImageSrc = (url: string | undefined): string => { ) { return parsed.href; } - // Restrict data: URIs to image and PDF MIME types only + // Restrict data: URIs to image and PDF MIME types only. + // Split on both ';' and ',' to handle both `data:type;base64,...` + // and `data:type,...` (non-base64 inline) formats. if (proto === "data:") { - const mime = parsed.pathname.split(";")[0].toLowerCase(); + const mime = parsed.pathname.split(/[;,]/)[0].toLowerCase(); if (mime.startsWith("image/") || mime === "application/pdf") { return parsed.href; } diff --git a/ui/litellm-dashboard/src/utils/storageUtils.ts b/ui/litellm-dashboard/src/utils/storageUtils.ts index b7db5a2c614..d723c4bdc94 100644 --- a/ui/litellm-dashboard/src/utils/storageUtils.ts +++ b/ui/litellm-dashboard/src/utils/storageUtils.ts @@ -14,11 +14,13 @@ */ function utf8ToBase64(str: string): string { const bytes = new TextEncoder().encode(str); - let binary = ""; - for (const b of bytes) { - binary += String.fromCharCode(b); + // Use chunked String.fromCharCode to avoid O(n²) string concatenation + const chunks: string[] = []; + const chunkSize = 8192; + for (let i = 0; i < bytes.length; i += chunkSize) { + chunks.push(String.fromCharCode(...bytes.subarray(i, i + chunkSize))); } - return btoa(binary); + return btoa(chunks.join("")); } /**