From 57f0f39f4dc834c274aaa417e74ce0f25dd9742b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 25 Feb 2026 21:14:21 +0100 Subject: [PATCH 1/5] Enhanced Markdown security by using SecurePipeline --- .../Chat/ContentBlockComponent.razor | 6 +- .../Chat/ContentBlockComponent.razor.cs | 109 +++++++++++++++++- .../Components/Changelog.razor | 2 +- .../Components/ChatComponent.razor | 3 +- .../Components/ConfidenceInfo.razor | 4 +- .../Settings/SettingsPanelProviders.razor | 2 +- .../Dialogs/DocumentCheckDialog.razor | 4 +- .../Dialogs/PandocDialog.razor | 4 +- .../Dialogs/UpdateDialog.razor | 4 +- app/MindWork AI Studio/Pages/Home.razor | 6 +- .../Pages/Information.razor | 2 +- app/MindWork AI Studio/Tools/Markdown.cs | 11 +- .../wwwroot/changelog/v26.3.1.md | 3 +- 13 files changed, 135 insertions(+), 25 deletions(-) diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor index 7c09ae78a..f3f2f5285 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor @@ -96,10 +96,10 @@ } else { - + @if (textContent.Sources.Count > 0) { - + } } } @@ -135,4 +135,4 @@ } } - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs index e29a016d9..17894232a 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs @@ -10,6 +10,18 @@ namespace AIStudio.Chat; /// public partial class ContentBlockComponent : MSGComponentBase { + private static readonly string[] HTML_TAG_MARKERS = + [ + " /// The role of the chat content block. /// @@ -68,18 +80,36 @@ public partial class ContentBlockComponent : MSGComponentBase private RustService RustService { get; init; } = null!; private bool HideContent { get; set; } + private bool hasRenderHash; + private int lastRenderHash; #region Overrides of ComponentBase protected override async Task OnInitializedAsync() { - // Register the streaming events: - this.Content.StreamingDone = this.AfterStreaming; - this.Content.StreamingEvent = () => this.InvokeAsync(this.StateHasChanged); - + this.RegisterStreamingEvents(); await base.OnInitializedAsync(); } + protected override Task OnParametersSetAsync() + { + this.RegisterStreamingEvents(); + return base.OnParametersSetAsync(); + } + + protected override bool ShouldRender() + { + var currentRenderHash = this.CreateRenderHash(); + if (!this.hasRenderHash || currentRenderHash != this.lastRenderHash) + { + this.lastRenderHash = currentRenderHash; + this.hasRenderHash = true; + return true; + } + + return false; + } + /// /// Gets called when the content stream ended. /// @@ -111,6 +141,47 @@ await this.InvokeAsync(async () => }); } + private void RegisterStreamingEvents() + { + this.Content.StreamingDone = this.AfterStreaming; + this.Content.StreamingEvent = () => this.InvokeAsync(this.StateHasChanged); + } + + private int CreateRenderHash() + { + var hash = new HashCode(); + hash.Add(this.Role); + hash.Add(this.Type); + hash.Add(this.Time); + hash.Add(this.Class); + hash.Add(this.IsLastContentBlock); + hash.Add(this.IsSecondToLastBlock); + hash.Add(this.HideContent); + hash.Add(this.SettingsManager.IsDarkMode); + hash.Add(this.RegenerateEnabled()); + hash.Add(this.Content.InitialRemoteWait); + hash.Add(this.Content.IsStreaming); + hash.Add(this.Content.FileAttachments.Count); + hash.Add(this.Content.Sources.Count); + + switch (this.Content) + { + case ContentText text: + var textValue = text.Text ?? string.Empty; + hash.Add(textValue.Length); + hash.Add(textValue.GetHashCode(StringComparison.Ordinal)); + hash.Add(text.Sources.Count); + break; + + case ContentImage image: + hash.Add(image.SourceType); + hash.Add(image.Source); + break; + } + + return hash.ToHashCode(); + } + #endregion private string CardClasses => $"my-2 rounded-lg {this.Class}"; @@ -121,6 +192,34 @@ await this.InvokeAsync(async () => { CodeBlock = { Theme = this.CodeColorPalette }, }; + + private string NormalizeMarkdownForRendering(string text) + { + var cleaned = text.RemoveThinkTags().Trim(); + if (string.IsNullOrWhiteSpace(cleaned)) + return string.Empty; + + if (cleaned.Contains("```", StringComparison.Ordinal)) + return cleaned; + + if (LooksLikeRawHtml(cleaned)) + return $"```html{Environment.NewLine}{cleaned}{Environment.NewLine}```"; + + return cleaned; + } + + private static bool LooksLikeRawHtml(string text) + { + var content = text.TrimStart(); + if (!content.StartsWith("<", StringComparison.Ordinal)) + return false; + + foreach (var marker in HTML_TAG_MARKERS) + if (content.Contains(marker, StringComparison.OrdinalIgnoreCase)) + return true; + + return content.Contains("", StringComparison.Ordinal); + } private async Task RemoveBlock() { @@ -194,4 +293,4 @@ private async Task OpenAttachmentsDialog() var result = await ReviewAttachmentsDialog.OpenDialogAsync(this.DialogService, this.Content.FileAttachments.ToHashSet()); this.Content.FileAttachments = result.ToList(); } -} \ No newline at end of file +} diff --git a/app/MindWork AI Studio/Components/Changelog.razor b/app/MindWork AI Studio/Components/Changelog.razor index 1afebfc37..2d573afbc 100644 --- a/app/MindWork AI Studio/Components/Changelog.razor +++ b/app/MindWork AI Studio/Components/Changelog.razor @@ -6,4 +6,4 @@ } - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor b/app/MindWork AI Studio/Components/ChatComponent.razor index 52b82b9bc..1467c01e8 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor +++ b/app/MindWork AI Studio/Components/ChatComponent.razor @@ -16,6 +16,7 @@ @if (!block.HideFromUser) { - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Components/ConfidenceInfo.razor b/app/MindWork AI Studio/Components/ConfidenceInfo.razor index f27fe58eb..ed7c45ef6 100644 --- a/app/MindWork AI Studio/Components/ConfidenceInfo.razor +++ b/app/MindWork AI Studio/Components/ConfidenceInfo.razor @@ -28,7 +28,7 @@ @T("Description") - + @if (this.currentConfidence.Sources.Count > 0) { @@ -67,4 +67,4 @@ - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor index f6704dc5d..f89d7b529 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor @@ -104,7 +104,7 @@ @context.ToName() - + diff --git a/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor b/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor index f3b758373..dc2ee563a 100644 --- a/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor +++ b/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor @@ -54,7 +54,7 @@ Class="ma-2 pe-4" HelperText="@T("This is the content we loaded from your file — including headings, lists, and formatting. Use this to verify your file loads as expected.")">
- +
@@ -83,4 +83,4 @@ @T("Close") - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDialog.razor index 2914b38e4..f9638ff99 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor @@ -30,7 +30,7 @@ } else if (!string.IsNullOrWhiteSpace(this.licenseText)) { - + } @@ -226,4 +226,4 @@ } } - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Dialogs/UpdateDialog.razor b/app/MindWork AI Studio/Dialogs/UpdateDialog.razor index 62f3dd7ac..3eaa6db99 100644 --- a/app/MindWork AI Studio/Dialogs/UpdateDialog.razor +++ b/app/MindWork AI Studio/Dialogs/UpdateDialog.razor @@ -5,7 +5,7 @@ @this.HeaderText - + @@ -15,4 +15,4 @@ @T("Install now") - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Pages/Home.razor b/app/MindWork AI Studio/Pages/Home.razor index 53d48e6ed..43118b243 100644 --- a/app/MindWork AI Studio/Pages/Home.razor +++ b/app/MindWork AI Studio/Pages/Home.razor @@ -27,7 +27,7 @@ - + @@ -35,9 +35,9 @@ - + - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Pages/Information.razor b/app/MindWork AI Studio/Pages/Information.razor index 435a6a564..e93892379 100644 --- a/app/MindWork AI Studio/Pages/Information.razor +++ b/app/MindWork AI Studio/Pages/Information.razor @@ -297,7 +297,7 @@ - + diff --git a/app/MindWork AI Studio/Tools/Markdown.cs b/app/MindWork AI Studio/Tools/Markdown.cs index 0ecf37744..24946386b 100644 --- a/app/MindWork AI Studio/Tools/Markdown.cs +++ b/app/MindWork AI Studio/Tools/Markdown.cs @@ -1,7 +1,16 @@ +using Markdig; + namespace AIStudio.Tools; public static class Markdown { + private static readonly MarkdownPipeline SAFE_MARKDOWN_PIPELINE = new MarkdownPipelineBuilder() + .UseAdvancedExtensions() + .DisableHtml() + .Build(); + + public static MarkdownPipeline SecurePipeline => SAFE_MARKDOWN_PIPELINE; + public static MudMarkdownProps DefaultConfig => new() { Heading = @@ -19,4 +28,4 @@ public static class Markdown }, } }; -} \ No newline at end of file +} diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md index 840e2947c..7f4e3b461 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md @@ -2,4 +2,5 @@ - Improved the performance by caching the OS language detection and requesting the user language only once per app start. - Improved the user-language logging by limiting language detection logs to a single entry per app start. - Improved the logbook readability by removing non-readable special characters from log entries. -- Improved the logbook reliability by significantly reducing duplicate log entries. \ No newline at end of file +- Improved the logbook reliability by significantly reducing duplicate log entries. +- Fixed an issue where the app could turn white or appear invisible in certain chats after HTML-like content was shown. \ No newline at end of file From 0fdaf19168799074512a90e2a8f92044546b56bc Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 25 Feb 2026 21:14:39 +0100 Subject: [PATCH 2/5] Added manual integration tests --- tests/README.md | 16 +++ tests/integration_tests/README.md | 12 ++ .../chat/chat_rendering_regression_tests.md | 120 ++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/integration_tests/README.md create mode 100644 tests/integration_tests/chat/chat_rendering_regression_tests.md diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..1856f2175 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,16 @@ +# Test Documentation + +This directory stores manual and automated test definitions for MindWork AI Studio. + +## Directory Structure + +- `integration_tests/`: Cross-component and end-to-end scenarios. + +## Authoring Rules + +- Use US English. +- Keep each feature area in its own Markdown file. +- Prefer stable test IDs (for example: `TC-CHAT-001`). +- Record expected behavior for: + - known vulnerable baseline builds (if relevant), + - current fixed builds. diff --git a/tests/integration_tests/README.md b/tests/integration_tests/README.md new file mode 100644 index 000000000..aa23175e4 --- /dev/null +++ b/tests/integration_tests/README.md @@ -0,0 +1,12 @@ +# Integration Tests + +This directory contains integration-oriented test specs. + +## Scope + +- Behavior that depends on multiple layers working together (UI, rendering, runtime, IPC, provider responses). +- Regressions that are hard to catch with unit tests only. + +## Current Feature Areas + +- `chat/`: Chat rendering, input interaction, and message lifecycle. diff --git a/tests/integration_tests/chat/chat_rendering_regression_tests.md b/tests/integration_tests/chat/chat_rendering_regression_tests.md new file mode 100644 index 000000000..ba773f54a --- /dev/null +++ b/tests/integration_tests/chat/chat_rendering_regression_tests.md @@ -0,0 +1,120 @@ +# Chat Rendering Regression Tests + +## Purpose + +Validate that chat rendering remains stable and interactive when model output or user input contains raw HTML/CSS/JS-like payloads. + +## Test Type + +Manual regression and integration checks. + +## Preconditions + +1. You can run two builds: + - a known vulnerable baseline build, + - the current fixed build. +2. At least one provider is configured and can answer prompts. +3. Open the Chat page. + +## Execution Flow (for each test case) + +1. Copy the test prompt exactly into the user prompt field. +2. Send the prompt. +3. Observe behavior immediately after send. +4. If the UI is still visible, type additional text in the prompt input. +5. Repeat on both builds. + +## Test Cases + +### TC-CHAT-001 - CSS Kill Switch + +**Prompt** + +```text +Respond with exactly the content below. No explanations, no Markdown code fences, no backticks. + + +
TEST
+``` + +**Expected result (vulnerable baseline)** +UI may turn into a white/invisible page immediately after sending. + +**Expected result (fixed build)** +Chat stays visible and usable. Content is rendered as inert text/code, not active page styling. + +--- + +### TC-CHAT-002 - Full White Overlay + +**Prompt** + +```text +Respond with exactly the content below. No explanations, no Markdown code fences, no backticks. + + +
TEST
+``` + +**Expected result (vulnerable baseline)** +UI may become fully white and non-interactive immediately after sending. + +**Expected result (fixed build)** +No overlay takes over the app. Chat remains interactive. + +--- + +### TC-CHAT-003 - Inline Event Handler Injection + +**Prompt** + +```text +Respond with exactly the content below. No explanations, no Markdown code fences, no backticks. + + +
TEST
+``` + +**Expected result (vulnerable baseline)** +UI may break/blank immediately after sending. + +**Expected result (fixed build)** +No JavaScript execution from message content. Chat remains stable. + +--- + +### TC-CHAT-004 - SVG Onload Injection Attempt + +**Prompt** + +```text +Respond with exactly the content below. No explanations, no Markdown code fences, no backticks. + + +
TEST
+``` + +**Expected result (vulnerable baseline)** +May or may not trigger depending on parser/runtime behavior. + +**Expected result (fixed build)** +No script-like execution from content. Chat remains stable and interactive. + +## Notes + +- If a test fails on the fixed build, capture: + - exact prompt used, + - whether failure happened right after send or while typing, + - whether a refresh restores the app. From 1353345311384244adaf1697ed1f580b2b99aadb Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 25 Feb 2026 21:27:48 +0100 Subject: [PATCH 3/5] Switched to SAFE_MARKDOWN_PIPELINE --- app/MindWork AI Studio/Chat/ContentBlockComponent.razor | 6 +++--- app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs | 7 ++++--- app/MindWork AI Studio/Components/Changelog.razor | 2 +- app/MindWork AI Studio/Components/ChatComponent.razor | 2 +- app/MindWork AI Studio/Components/ConfidenceInfo.razor | 4 ++-- .../Components/Settings/SettingsPanelProviders.razor | 2 +- app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor | 4 ++-- app/MindWork AI Studio/Dialogs/PandocDialog.razor | 4 ++-- app/MindWork AI Studio/Dialogs/UpdateDialog.razor | 4 ++-- app/MindWork AI Studio/Pages/Home.razor | 6 +++--- app/MindWork AI Studio/Pages/Information.razor | 4 ++-- app/MindWork AI Studio/Tools/Markdown.cs | 6 ++---- 12 files changed, 25 insertions(+), 26 deletions(-) diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor index f3f2f5285..579e8bf2f 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor @@ -96,10 +96,10 @@ } else { - + @if (textContent.Sources.Count > 0) { - + } } } @@ -135,4 +135,4 @@ } } - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs index 17894232a..29e704870 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs @@ -97,6 +97,7 @@ protected override Task OnParametersSetAsync() return base.OnParametersSetAsync(); } + /// protected override bool ShouldRender() { var currentRenderHash = this.CreateRenderHash(); @@ -167,7 +168,7 @@ private int CreateRenderHash() switch (this.Content) { case ContentText text: - var textValue = text.Text ?? string.Empty; + var textValue = text.Text; hash.Add(textValue.Length); hash.Add(textValue.GetHashCode(StringComparison.Ordinal)); hash.Add(text.Sources.Count); @@ -193,7 +194,7 @@ private int CreateRenderHash() CodeBlock = { Theme = this.CodeColorPalette }, }; - private string NormalizeMarkdownForRendering(string text) + private static string NormalizeMarkdownForRendering(string text) { var cleaned = text.RemoveThinkTags().Trim(); if (string.IsNullOrWhiteSpace(cleaned)) @@ -293,4 +294,4 @@ private async Task OpenAttachmentsDialog() var result = await ReviewAttachmentsDialog.OpenDialogAsync(this.DialogService, this.Content.FileAttachments.ToHashSet()); this.Content.FileAttachments = result.ToList(); } -} +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Changelog.razor b/app/MindWork AI Studio/Components/Changelog.razor index 2d573afbc..7ee430217 100644 --- a/app/MindWork AI Studio/Components/Changelog.razor +++ b/app/MindWork AI Studio/Components/Changelog.razor @@ -6,4 +6,4 @@ } - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor b/app/MindWork AI Studio/Components/ChatComponent.razor index 1467c01e8..3c49a4b5e 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor +++ b/app/MindWork AI Studio/Components/ChatComponent.razor @@ -127,4 +127,4 @@ - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ConfidenceInfo.razor b/app/MindWork AI Studio/Components/ConfidenceInfo.razor index ed7c45ef6..0bf2d0440 100644 --- a/app/MindWork AI Studio/Components/ConfidenceInfo.razor +++ b/app/MindWork AI Studio/Components/ConfidenceInfo.razor @@ -28,7 +28,7 @@ @T("Description") - + @if (this.currentConfidence.Sources.Count > 0) { @@ -67,4 +67,4 @@ - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor index f89d7b529..8a862702c 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor @@ -104,7 +104,7 @@ @context.ToName()
- + diff --git a/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor b/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor index dc2ee563a..8936e04eb 100644 --- a/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor +++ b/app/MindWork AI Studio/Dialogs/DocumentCheckDialog.razor @@ -54,7 +54,7 @@ Class="ma-2 pe-4" HelperText="@T("This is the content we loaded from your file — including headings, lists, and formatting. Use this to verify your file loads as expected.")">
- +
@@ -83,4 +83,4 @@ @T("Close") - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDialog.razor index f9638ff99..c4f2ac3e2 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor @@ -30,7 +30,7 @@ } else if (!string.IsNullOrWhiteSpace(this.licenseText)) { - + } @@ -226,4 +226,4 @@ } } - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/UpdateDialog.razor b/app/MindWork AI Studio/Dialogs/UpdateDialog.razor index 3eaa6db99..f53455235 100644 --- a/app/MindWork AI Studio/Dialogs/UpdateDialog.razor +++ b/app/MindWork AI Studio/Dialogs/UpdateDialog.razor @@ -5,7 +5,7 @@ @this.HeaderText - + @@ -15,4 +15,4 @@ @T("Install now") - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/Home.razor b/app/MindWork AI Studio/Pages/Home.razor index 43118b243..eae947abc 100644 --- a/app/MindWork AI Studio/Pages/Home.razor +++ b/app/MindWork AI Studio/Pages/Home.razor @@ -27,7 +27,7 @@ - + @@ -35,9 +35,9 @@ - + - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/Information.razor b/app/MindWork AI Studio/Pages/Information.razor index e93892379..a859a142e 100644 --- a/app/MindWork AI Studio/Pages/Information.razor +++ b/app/MindWork AI Studio/Pages/Information.razor @@ -297,8 +297,8 @@ - + - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Markdown.cs b/app/MindWork AI Studio/Tools/Markdown.cs index 24946386b..49a2309c6 100644 --- a/app/MindWork AI Studio/Tools/Markdown.cs +++ b/app/MindWork AI Studio/Tools/Markdown.cs @@ -4,13 +4,11 @@ namespace AIStudio.Tools; public static class Markdown { - private static readonly MarkdownPipeline SAFE_MARKDOWN_PIPELINE = new MarkdownPipelineBuilder() + public static readonly MarkdownPipeline SAFE_MARKDOWN_PIPELINE = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .DisableHtml() .Build(); - public static MarkdownPipeline SecurePipeline => SAFE_MARKDOWN_PIPELINE; - public static MudMarkdownProps DefaultConfig => new() { Heading = @@ -28,4 +26,4 @@ public static class Markdown }, } }; -} +} \ No newline at end of file From ed417a15b54bfc3818a5ae24fae266fa08bb4b86 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 25 Feb 2026 21:31:41 +0100 Subject: [PATCH 4/5] Updated changelog --- app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md index 7f4e3b461..0ec7db3da 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md @@ -3,4 +3,4 @@ - Improved the user-language logging by limiting language detection logs to a single entry per app start. - Improved the logbook readability by removing non-readable special characters from log entries. - Improved the logbook reliability by significantly reducing duplicate log entries. -- Fixed an issue where the app could turn white or appear invisible in certain chats after HTML-like content was shown. \ No newline at end of file +- Fixed an issue where the app could turn white or appear invisible in certain chats after HTML-like content was shown. Thanks Inga for reporting this issue and providing some context on how to reproduce it. \ No newline at end of file From a69a8746422dd7c7d4ca9027e1d988066c27c430 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 25 Feb 2026 21:37:02 +0100 Subject: [PATCH 5/5] Updated changelog --- app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md index 0ec7db3da..f5bd763bd 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.3.1.md @@ -1,5 +1,6 @@ # v26.3.1, build 235 (2026-03-xx xx:xx UTC) - Improved the performance by caching the OS language detection and requesting the user language only once per app start. +- Improved the chat performance by reducing unnecessary UI updates, making chats smoother and more responsive, especially in longer conversations. - Improved the user-language logging by limiting language detection logs to a single entry per app start. - Improved the logbook readability by removing non-readable special characters from log entries. - Improved the logbook reliability by significantly reducing duplicate log entries.