From e739468a854e6817cb79889677075b9d8c80a081 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 10 Aug 2026 19:58:39 +0200 Subject: [PATCH] Fixed slide images reaching the AI as raw Base64 data --- .../Tools/ContentStreamSseHandler.cs | 27 ++++++++++++++++++- .../Tools/DocumentManager.cs | 7 +++-- .../Tools/SlideImageContent.cs | 10 ++++--- app/MindWork AI Studio/Tools/SlideManager.cs | 16 +++++------ 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/app/MindWork AI Studio/Tools/ContentStreamSseHandler.cs b/app/MindWork AI Studio/Tools/ContentStreamSseHandler.cs index d333b7b1..564186be 100644 --- a/app/MindWork AI Studio/Tools/ContentStreamSseHandler.cs +++ b/app/MindWork AI Studio/Tools/ContentStreamSseHandler.cs @@ -132,7 +132,32 @@ public static class ContentStreamSseHandler CHUNKED_IMAGES.Remove(id, out _); return base64Image; } - + + /// + /// Assembles the collected segments of an image into a Markdown image. + /// + /// + /// Handing the naked Base64 data to the AI says nothing: it is neither readable text nor an + /// image it could look at. Only the data URI makes it one, so every reader must embed its + /// images this way. + /// + /// The ID of the image to assemble. + /// The media type the runtime reported, if any. + /// The Markdown image, or null when no data was collected for that ID. + public static string? BuildImageMarkdown(string id, string? mediaType) + { + var base64Image = BuildImage(id); + if (string.IsNullOrWhiteSpace(base64Image)) + return null; + + // + // Both readers compress their images, and that compression produces JPEG. A runtime which + // does not report the media type therefore delivered JPEG as well. + // + var imageMediaType = string.IsNullOrWhiteSpace(mediaType) ? "image/jpeg" : mediaType; + return $"![Image](data:{imageMediaType};base64,{base64Image})"; + } + public static string? Clear(string streamId) { if (string.IsNullOrWhiteSpace(streamId)) diff --git a/app/MindWork AI Studio/Tools/DocumentManager.cs b/app/MindWork AI Studio/Tools/DocumentManager.cs index 875a4771..8183987e 100644 --- a/app/MindWork AI Studio/Tools/DocumentManager.cs +++ b/app/MindWork AI Studio/Tools/DocumentManager.cs @@ -31,12 +31,11 @@ public sealed class DocumentManager if (ContentStreamSseHandler.ProcessImageSegment(image.Id, image)) { - var base64 = ContentStreamSseHandler.BuildImage(image.Id); - if (!string.IsNullOrWhiteSpace(base64)) + var markdownImage = ContentStreamSseHandler.BuildImageMarkdown(image.Id, image.MediaType); + if (markdownImage is not null) { - var mediaType = string.IsNullOrWhiteSpace(image.MediaType) ? "image/jpeg" : image.MediaType; this.currentPageContent.AppendLine(); - this.currentPageContent.AppendLine($"![Image](data:{mediaType};base64,{base64})"); + this.currentPageContent.AppendLine(markdownImage); } } diff --git a/app/MindWork AI Studio/Tools/SlideImageContent.cs b/app/MindWork AI Studio/Tools/SlideImageContent.cs index ec261436..10dc6add 100644 --- a/app/MindWork AI Studio/Tools/SlideImageContent.cs +++ b/app/MindWork AI Studio/Tools/SlideImageContent.cs @@ -1,8 +1,10 @@ -using System.Text; - namespace AIStudio.Tools; -public sealed class SlideImageContent(string base64Image) : ISlideContent +/// +/// An image of a slide, ready to be appended to the slide's Markdown. +/// +/// The image as a Markdown image with an embedded data URI. +public sealed class SlideImageContent(string markdownImage) : ISlideContent { - public StringBuilder Base64Image => new(base64Image); + public string MarkdownImage => markdownImage; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/SlideManager.cs b/app/MindWork AI Studio/Tools/SlideManager.cs index 47407bd1..f6ed1ea6 100644 --- a/app/MindWork AI Studio/Tools/SlideManager.cs +++ b/app/MindWork AI Studio/Tools/SlideManager.cs @@ -52,11 +52,11 @@ public sealed class SlideManager // if (addImage) { - var img = ContentStreamSseHandler.BuildImage(image!.Id!); - var slideImage = new SlideImageContent(img); - createdSlide.Content.Add(slideImage); + var markdownImage = ContentStreamSseHandler.BuildImageMarkdown(image!.Id!, image.MediaType); + if (markdownImage is not null) + createdSlide.Content.Add(new SlideImageContent(markdownImage)); } - + this.slides[slideNumber] = createdSlide; } else @@ -75,9 +75,9 @@ public sealed class SlideManager // Add any image content? if (addImage) { - var img = ContentStreamSseHandler.BuildImage(image!.Id!); - var slideImage = new SlideImageContent(img); - slide.Content.Add(slideImage); + var markdownImage = ContentStreamSseHandler.BuildImageMarkdown(image!.Id!, image.MediaType); + if (markdownImage is not null) + slide.Content.Add(new SlideImageContent(markdownImage)); } } } @@ -96,7 +96,7 @@ public sealed class SlideManager foreach (var image in slide.Content.OfType()) { - content.AppendLine(image.Base64Image.ToString()); + content.AppendLine(image.MarkdownImage); content.AppendLine(); } }