Skip to content

Commit 8fee312

Browse files
mrubensroomote
andauthored
Bust cache in generated image preview (#7860)
Co-authored-by: Roo Code <[email protected]>
1 parent 3b1a6d1 commit 8fee312

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

src/core/tools/__tests__/generateImageTool.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,60 @@ describe("generateImageTool", () => {
163163
expect(mockGenerateImage).toHaveBeenCalled()
164164
expect(mockPushToolResult).toHaveBeenCalled()
165165
})
166+
167+
it("should add cache-busting parameter to image URI", async () => {
168+
const completeBlock: ToolUse = {
169+
type: "tool_use",
170+
name: "generate_image",
171+
params: {
172+
prompt: "Generate a test image",
173+
path: "test-image.png",
174+
},
175+
partial: false,
176+
}
177+
178+
// Mock convertToWebviewUri to return a test URI
179+
const mockWebviewUri = "https://file+.vscode-resource.vscode-cdn.net/test/workspace/test-image.png"
180+
mockCline.providerRef.deref().convertToWebviewUri = vi.fn().mockReturnValue(mockWebviewUri)
181+
182+
// Mock the OpenRouterHandler generateImage method
183+
const mockGenerateImage = vi.fn().mockResolvedValue({
184+
success: true,
185+
imageData: "data:image/png;base64,fakebase64data",
186+
})
187+
188+
vi.mocked(OpenRouterHandler).mockImplementation(
189+
() =>
190+
({
191+
generateImage: mockGenerateImage,
192+
}) as any,
193+
)
194+
195+
await generateImageTool(
196+
mockCline as Task,
197+
completeBlock,
198+
mockAskApproval,
199+
mockHandleError,
200+
mockPushToolResult,
201+
mockRemoveClosingTag,
202+
)
203+
204+
// Check that cline.say was called with image data containing cache-busting parameter
205+
expect(mockCline.say).toHaveBeenCalledWith("image", expect.stringMatching(/"imageUri":"[^"]+\?t=\d+"/))
206+
207+
// Verify the imageUri contains the cache-busting parameter
208+
const sayCall = mockCline.say.mock.calls.find((call: any[]) => call[0] === "image")
209+
if (sayCall) {
210+
const imageData = JSON.parse(sayCall[1])
211+
expect(imageData.imageUri).toMatch(/\?t=\d+$/)
212+
// Handle both Unix and Windows path separators
213+
const expectedPath =
214+
process.platform === "win32"
215+
? "\\test\\workspace\\test-image.png"
216+
: "/test/workspace/test-image.png"
217+
expect(imageData.imagePath).toBe(expectedPath)
218+
}
219+
})
166220
})
167221

168222
describe("missing parameters", () => {

src/core/tools/generateImageTool.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,11 @@ export async function generateImageTool(
244244
const fullImagePath = path.join(cline.cwd, finalPath)
245245

246246
// Convert to webview URI if provider is available
247-
const imageUri = provider?.convertToWebviewUri?.(fullImagePath) ?? vscode.Uri.file(fullImagePath).toString()
247+
let imageUri = provider?.convertToWebviewUri?.(fullImagePath) ?? vscode.Uri.file(fullImagePath).toString()
248+
249+
// Add cache-busting parameter to prevent browser caching issues
250+
const cacheBuster = Date.now()
251+
imageUri = imageUri.includes("?") ? `${imageUri}&t=${cacheBuster}` : `${imageUri}?t=${cacheBuster}`
248252

249253
// Send the image with the webview URI
250254
await cline.say("image", JSON.stringify({ imageUri, imagePath: fullImagePath }))

0 commit comments

Comments
 (0)