diff --git a/src/integrations/misc/__tests__/imageDataUrl.spec.ts b/src/integrations/misc/__tests__/imageDataUrl.spec.ts index 8aef7d69fc..bcbbe048df 100644 --- a/src/integrations/misc/__tests__/imageDataUrl.spec.ts +++ b/src/integrations/misc/__tests__/imageDataUrl.spec.ts @@ -1,8 +1,7 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" -import { normalizeImageRefsToDataUrls, normalizeDataUrlsToFilePaths } from "../imageDataUrl" +import { describe, it, expect, vi, beforeEach } from "vitest" +import { normalizeImageRefsToDataUrls } from "../imageDataUrl" import * as fs from "fs/promises" import * as path from "path" -import * as os from "os" // Mock fs module vi.mock("fs/promises") @@ -64,97 +63,3 @@ describe("normalizeImageRefsToDataUrls", () => { expect(result).toEqual([]) }) }) - -describe("normalizeDataUrlsToFilePaths", () => { - const testGlobalStoragePath = path.join(os.tmpdir(), "test-roo-code-storage") - - beforeEach(async () => { - vi.clearAllMocks() - // Mock mkdir to succeed - vi.mocked(fs.mkdir).mockResolvedValue(undefined) - // Mock writeFile to succeed - vi.mocked(fs.writeFile).mockResolvedValue(undefined) - // Mock access to fail initially (file doesn't exist) - vi.mocked(fs.access).mockRejectedValue(new Error("File not found")) - }) - - afterEach(() => { - vi.clearAllMocks() - }) - - it("should pass through non-data URLs unchanged", async () => { - const filePath = "/path/to/image.png" - const result = await normalizeDataUrlsToFilePaths([filePath], testGlobalStoragePath) - - expect(result).toEqual([filePath]) - expect(fs.writeFile).not.toHaveBeenCalled() - }) - - it("should convert data URLs to file paths", async () => { - const dataUrl = - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==" - - const result = await normalizeDataUrlsToFilePaths([dataUrl], testGlobalStoragePath) - - expect(result).toHaveLength(1) - expect(result[0]).toMatch(/temp-images/) - expect(result[0]).toMatch(/\.png$/) - expect(fs.mkdir).toHaveBeenCalledWith( - expect.stringContaining("temp-images"), - expect.objectContaining({ recursive: true }), - ) - expect(fs.writeFile).toHaveBeenCalledWith(expect.stringMatching(/temp-images.*\.png$/), expect.any(Buffer)) - }) - - it("should handle mixed arrays of data URLs and file paths", async () => { - const dataUrl = "data:image/jpeg;base64,test123" - const filePath = "/existing/image.png" - - const result = await normalizeDataUrlsToFilePaths([filePath, dataUrl], testGlobalStoragePath) - - expect(result).toHaveLength(2) - expect(result[0]).toBe(filePath) // File path unchanged - expect(result[1]).toMatch(/temp-images/) // Data URL converted - expect(result[1]).toMatch(/\.jpeg$/) // Correct extension from MIME type - }) - - it("should handle errors gracefully", async () => { - const dataUrl = "data:image/png;base64,test" - - // Mock writeFile to fail - vi.mocked(fs.writeFile).mockRejectedValue(new Error("Write failed")) - - const result = await normalizeDataUrlsToFilePaths([dataUrl], testGlobalStoragePath) - - // Should return original data URL as fallback - expect(result).toEqual([dataUrl]) - }) - - it("should handle invalid data URL format", async () => { - const invalidDataUrl = "data:image/png" // Missing base64 data - - const result = await normalizeDataUrlsToFilePaths([invalidDataUrl], testGlobalStoragePath) - - // Should skip invalid URLs - expect(result).toHaveLength(0) - }) - - it("should handle empty arrays", async () => { - const result = await normalizeDataUrlsToFilePaths([], testGlobalStoragePath) - expect(result).toEqual([]) - }) - - it("should extract correct file extensions from MIME types", async () => { - const testCases = [ - { dataUrl: "data:image/png;base64,test", expectedExt: ".png" }, - { dataUrl: "data:image/jpeg;base64,test", expectedExt: ".jpeg" }, - { dataUrl: "data:image/gif;base64,test", expectedExt: ".gif" }, - { dataUrl: "data:image/webp;base64,test", expectedExt: ".webp" }, - ] - - for (const { dataUrl, expectedExt } of testCases) { - const result = await normalizeDataUrlsToFilePaths([dataUrl], testGlobalStoragePath) - expect(result[0]).toMatch(new RegExp(`${expectedExt.replace(".", "\\.")}$`)) - } - }) -}) diff --git a/src/integrations/misc/imageDataUrl.ts b/src/integrations/misc/imageDataUrl.ts index a764b92d83..42d93606f7 100644 --- a/src/integrations/misc/imageDataUrl.ts +++ b/src/integrations/misc/imageDataUrl.ts @@ -1,7 +1,6 @@ import * as fs from "fs/promises" import * as path from "path" -import * as crypto from "crypto" -import { getImageBase64ForPath, setImageBase64ForPath } from "./image-cache" +import { getImageBase64ForPath } from "./image-cache" /** * Converts webview URIs to base64 data URLs for API calls. @@ -44,70 +43,6 @@ export async function normalizeImageRefsToDataUrls(imageRefs: string[]): Promise return results } -/** - * Converts base64 data URLs to file paths suitable for webview URIs. - * Writes base64 images to temporary files and returns their paths. - * - * NOTE: This function is primarily used for testing. In production, the dual-storage - * approach (images + imagesBase64 in ClineMessage) eliminates the need for this conversion. - * No caching is implemented since this is a test utility. - */ -export async function normalizeDataUrlsToFilePaths(dataUrls: string[], globalStoragePath: string): Promise { - const results: string[] = [] - - // Ensure temp directory exists - const tempDir = path.join(globalStoragePath, "temp-images") - try { - await fs.mkdir(tempDir, { recursive: true }) - } catch (error) { - console.error("Failed to create temp-images directory:", error) - return dataUrls // Return original data URLs as fallback - } - - for (const dataUrl of dataUrls) { - // If it's not a data URL, keep it as is (might be a file path already) - if (!dataUrl.startsWith("data:image/")) { - results.push(dataUrl) - continue - } - - try { - // Extract base64 data and MIME type - const commaIndex = dataUrl.indexOf(",") - if (commaIndex === -1) { - console.error("Invalid data URL format:", dataUrl.substring(0, 50)) - continue - } - - const header = dataUrl.substring(0, commaIndex) - const base64Data = dataUrl.substring(commaIndex + 1) - - // Determine file extension from MIME type - const mimeMatch = header.match(/data:image\/([^;]+)/) - const extension = mimeMatch ? `.${mimeMatch[1]}` : ".png" - - // Create a unique hash for this image - const hash = crypto.createHash("md5").update(dataUrl).digest("hex") - - // Write to temp file - const filePath = path.join(tempDir, `${hash}${extension}`) - const buffer = Buffer.from(base64Data, "base64") - await fs.writeFile(filePath, buffer) - - // Cache the reverse mapping for image-cache lookups - setImageBase64ForPath(filePath, dataUrl) - - results.push(filePath) - } catch (error) { - console.error("Failed to convert base64 data URL to file path:", error) - // Keep the original data URL as fallback - results.push(dataUrl) - } - } - - return results -} - /** * Converts a webview URI to a file system path */