diff --git a/apps/web/app/components/chat-message.tsx b/apps/web/app/components/chat-message.tsx index e1b0b278243..3361cb4edd3 100644 --- a/apps/web/app/components/chat-message.tsx +++ b/apps/web/app/components/chat-message.tsx @@ -555,7 +555,7 @@ function createMarkdownComponents( onFilePathClick?: FilePathClickHandler, ): Components { return { - // Open external links in new tab + // Open external links in new tab; intercept local file-path links a: ({ href, children, ...props }) => { const rawHref = typeof href === "string" ? href : ""; const normalizedHref = normalizePathReference(rawHref); @@ -583,15 +583,18 @@ function createMarkdownComponents( ); }, - // Render images with loading=lazy - img: ({ src, alt, ...props }) => ( - // eslint-disable-next-line @next/next/no-img-element - {alt - ), + // Route local image paths through raw-file API so workspace images render + img: ({ src, alt, ...props }) => { + const resolvedSrc = typeof src === "string" && !src.startsWith("http://") && !src.startsWith("https://") && !src.startsWith("data:") + ? `/api/workspace/raw-file?path=${encodeURIComponent(src)}` + : src; + return ( + // eslint-disable-next-line @next/next/no-img-element + {alt + ); + }, // Syntax-highlighted fenced code blocks pre: ({ children, ...props }) => { - // react-markdown wraps code blocks in
...
-			// Extract the code element to get lang + content
 			const child = Array.isArray(children) ? children[0] : children;
 			if (
 				child &&