From ed4c7d215a2e9c0f75b6368b0330608104223006 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 28 Dec 2025 16:50:36 +0100 Subject: [PATCH] Refactored file attachments (#608) --- .../DocumentAnalysisAssistant.razor.cs | 16 +++-- app/MindWork AI Studio/Chat/ContentImage.cs | 2 +- app/MindWork AI Studio/Chat/ContentText.cs | 36 ++++++---- app/MindWork AI Studio/Chat/FileAttachment.cs | 71 +++++++++++++++++++ .../Chat/FileAttachmentType.cs | 27 +++++++ app/MindWork AI Studio/Chat/IContent.cs | 4 +- .../Components/AttachDocuments.razor | 4 +- .../Components/AttachDocuments.razor.cs | 31 ++++---- .../Components/ChatComponent.razor.cs | 4 +- .../Dialogs/ReviewAttachmentsDialog.razor | 16 ++--- .../Dialogs/ReviewAttachmentsDialog.razor.cs | 23 +++--- .../AlibabaCloud/ProviderAlibabaCloud.cs | 2 +- .../Provider/Anthropic/ProviderAnthropic.cs | 2 +- .../Provider/DeepSeek/ProviderDeepSeek.cs | 2 +- .../Provider/Fireworks/ProviderFireworks.cs | 2 +- .../Provider/GWDG/ProviderGWDG.cs | 2 +- .../Provider/Google/ProviderGoogle.cs | 2 +- .../Provider/Groq/ProviderGroq.cs | 2 +- .../Provider/Helmholtz/ProviderHelmholtz.cs | 2 +- .../HuggingFace/ProviderHuggingFace.cs | 2 +- .../Provider/Mistral/ProviderMistral.cs | 2 +- .../Provider/OpenAI/ProviderOpenAI.cs | 2 +- .../Provider/OpenRouter/ProviderOpenRouter.cs | 2 +- .../Provider/Perplexity/ProviderPerplexity.cs | 2 +- .../Provider/SelfHosted/ProviderSelfHosted.cs | 2 +- .../Provider/X/ProviderX.cs | 2 +- 26 files changed, 188 insertions(+), 76 deletions(-) create mode 100644 app/MindWork AI Studio/Chat/FileAttachment.cs create mode 100644 app/MindWork AI Studio/Chat/FileAttachmentType.cs diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 994bafa8..d7ee8987 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -185,7 +185,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore loadedDocumentPaths = []; + private HashSet loadedDocumentPaths = []; private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected; @@ -330,13 +330,19 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore(); var count = 1; - foreach (var documentPath in this.loadedDocumentPaths) + foreach (var fileAttachment in this.loadedDocumentPaths) { - var fileContent = await this.RustService.ReadArbitraryFileData(documentPath, int.MaxValue); - + if (fileAttachment.IsForbidden) + { + this.Logger.LogWarning($"Skipping forbidden file: '{fileAttachment.FilePath}'."); + continue; + } + + var fileContent = await this.RustService.ReadArbitraryFileData(fileAttachment.FilePath, int.MaxValue); + documentSections.Add($""" ## DOCUMENT {count}: - File path: {documentPath} + File path: {fileAttachment.FilePath} Content: ``` {fileContent} diff --git a/app/MindWork AI Studio/Chat/ContentImage.cs b/app/MindWork AI Studio/Chat/ContentImage.cs index a6f385b8..4c162cac 100644 --- a/app/MindWork AI Studio/Chat/ContentImage.cs +++ b/app/MindWork AI Studio/Chat/ContentImage.cs @@ -32,7 +32,7 @@ public sealed class ContentImage : IContent, IImageSource public List Sources { get; set; } = []; /// - public List FileAttachments { get; set; } = []; + public List FileAttachments { get; set; } = []; /// public Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatChatThread, CancellationToken token = default) diff --git a/app/MindWork AI Studio/Chat/ContentText.cs b/app/MindWork AI Studio/Chat/ContentText.cs index c697a03d..b0a67f79 100644 --- a/app/MindWork AI Studio/Chat/ContentText.cs +++ b/app/MindWork AI Studio/Chat/ContentText.cs @@ -42,7 +42,7 @@ public sealed class ContentText : IContent public List Sources { get; set; } = []; /// - public List FileAttachments { get; set; } = []; + public List FileAttachments { get; set; } = []; /// public async Task CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatThread, CancellationToken token = default) @@ -149,24 +149,24 @@ public sealed class ContentText : IContent #endregion - public async Task PrepareContentForAI() + public async Task PrepareTextContentForAI() { var sb = new StringBuilder(); sb.AppendLine(this.Text); if(this.FileAttachments.Count > 0) { - // Filter out files that no longer exist - var existingFiles = this.FileAttachments.Where(File.Exists).ToList(); + // Get the list of existing documents: + var existingDocuments = this.FileAttachments.Where(x => x.Type is FileAttachmentType.DOCUMENT && x.Exists).ToList(); - // Log warning for missing files - var missingFiles = this.FileAttachments.Except(existingFiles).ToList(); - if (missingFiles.Count > 0) - foreach (var missingFile in missingFiles) - LOGGER.LogWarning("File attachment no longer exists and will be skipped: '{MissingFile}'", missingFile); - - // Only proceed if there are existing files - if (existingFiles.Count > 0) + // Log warning for missing files: + var missingDocuments = this.FileAttachments.Except(existingDocuments).Where(x => x.Type is FileAttachmentType.DOCUMENT).ToList(); + if (missingDocuments.Count > 0) + foreach (var missingDocument in missingDocuments) + LOGGER.LogWarning("File attachment no longer exists and will be skipped: '{MissingDocument}'.", missingDocument.FilePath); + + // Only proceed if there are existing, allowed documents: + if (existingDocuments.Count > 0) { // Check Pandoc availability once before processing file attachments var pandocState = await Pandoc.CheckAvailabilityAsync(Program.RUST_SERVICE, showMessages: true, showSuccessMessage: false); @@ -179,14 +179,20 @@ public sealed class ContentText : IContent { sb.AppendLine(); sb.AppendLine("The following files are attached to this message:"); - foreach(var file in existingFiles) + foreach(var document in existingDocuments) { + if (document.IsForbidden) + { + LOGGER.LogWarning("File attachment '{FilePath}' has a forbidden file type and will be skipped.", document.FilePath); + continue; + } + sb.AppendLine(); sb.AppendLine("---------------------------------------"); - sb.AppendLine($"File path: {file}"); + sb.AppendLine($"File path: {document.FilePath}"); sb.AppendLine("File content:"); sb.AppendLine("````"); - sb.AppendLine(await Program.RUST_SERVICE.ReadArbitraryFileData(file, int.MaxValue)); + sb.AppendLine(await Program.RUST_SERVICE.ReadArbitraryFileData(document.FilePath, int.MaxValue)); sb.AppendLine("````"); } } diff --git a/app/MindWork AI Studio/Chat/FileAttachment.cs b/app/MindWork AI Studio/Chat/FileAttachment.cs new file mode 100644 index 00000000..bacae923 --- /dev/null +++ b/app/MindWork AI Studio/Chat/FileAttachment.cs @@ -0,0 +1,71 @@ +using AIStudio.Tools.Rust; + +namespace AIStudio.Chat; + +/// +/// Represents an immutable file attachment with details about its type, name, path, and size. +/// +/// The type of the file attachment. +/// The name of the file, including extension. +/// The full path to the file, including the filename and extension. +/// The size of the file in bytes. +public readonly record struct FileAttachment(FileAttachmentType Type, string FileName, string FilePath, long FileSizeBytes) +{ + /// + /// Gets a value indicating whether the file still exists on the file system. + /// + public bool Exists => File.Exists(this.FilePath); + + /// + /// Gets a value indicating whether the file type is forbidden and should not be attached. + /// + public bool IsForbidden => this.Type == FileAttachmentType.FORBIDDEN; + + /// + /// Gets a value indicating whether the file type is valid and allowed to be attached. + /// + public bool IsValid => this.Type != FileAttachmentType.FORBIDDEN; + + /// + /// Creates a FileAttachment from a file path by automatically determining the type, + /// extracting the filename, and reading the file size. + /// + /// The full path to the file. + /// A FileAttachment instance with populated properties. + public static FileAttachment FromPath(string filePath) + { + var fileName = Path.GetFileName(filePath); + var fileSize = File.Exists(filePath) ? new FileInfo(filePath).Length : 0; + var type = DetermineFileType(filePath); + + return new FileAttachment(type, fileName, filePath, fileSize); + } + + /// + /// Determines the file attachment type based on the file extension. + /// Uses centrally defined file type filters from . + /// + /// The file path to analyze. + /// The corresponding FileAttachmentType. + private static FileAttachmentType DetermineFileType(string filePath) + { + var extension = Path.GetExtension(filePath).TrimStart('.').ToLowerInvariant(); + + // Check if it's an image file: + if (FileTypeFilter.AllImages.FilterExtensions.Contains(extension)) + return FileAttachmentType.IMAGE; + + // Check if it's an audio file: + if (FileTypeFilter.AllAudio.FilterExtensions.Contains(extension)) + return FileAttachmentType.AUDIO; + + // Check if it's an allowed document file (PDF, Text, or Office): + if (FileTypeFilter.PDF.FilterExtensions.Contains(extension) || + FileTypeFilter.Text.FilterExtensions.Contains(extension) || + FileTypeFilter.AllOffice.FilterExtensions.Contains(extension)) + return FileAttachmentType.DOCUMENT; + + // All other file types are forbidden: + return FileAttachmentType.FORBIDDEN; + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Chat/FileAttachmentType.cs b/app/MindWork AI Studio/Chat/FileAttachmentType.cs new file mode 100644 index 00000000..11185e94 --- /dev/null +++ b/app/MindWork AI Studio/Chat/FileAttachmentType.cs @@ -0,0 +1,27 @@ +namespace AIStudio.Chat; + +/// +/// Represents different types of file attachments. +/// +public enum FileAttachmentType +{ + /// + /// Document file types, such as .pdf, .docx, .txt, etc. + /// + DOCUMENT, + + /// + /// All image file types, such as .jpg, .png, .gif, etc. + /// + IMAGE, + + /// + /// All audio file types, such as .mp3, .wav, .aac, etc. + /// + AUDIO, + + /// + /// Forbidden file types that should not be attached, such as executables. + /// + FORBIDDEN, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Chat/IContent.cs b/app/MindWork AI Studio/Chat/IContent.cs index 883a1b6c..dea453f8 100644 --- a/app/MindWork AI Studio/Chat/IContent.cs +++ b/app/MindWork AI Studio/Chat/IContent.cs @@ -50,10 +50,10 @@ public interface IContent /// /// Represents a collection of file attachments associated with the content. - /// This property contains a list of file paths that are appended + /// This property contains a list of file attachments that are appended /// to the content to provide additional context or resources. /// - public List FileAttachments { get; set; } + public List FileAttachments { get; set; } /// /// Uses the provider to create the content. diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor index aea32e75..bc66f9c2 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor @@ -68,9 +68,9 @@ else
- @foreach (var filePath in this.DocumentPaths) + @foreach (var fileAttachment in this.DocumentPaths) { - + }
diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index 942ce861..a647876e 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -1,3 +1,4 @@ +using AIStudio.Chat; using AIStudio.Dialogs; using AIStudio.Tools.PluginSystem; using AIStudio.Tools.Rust; @@ -16,15 +17,15 @@ public partial class AttachDocuments : MSGComponentBase [Parameter] public string Name { get; set; } = string.Empty; - + [Parameter] - public HashSet DocumentPaths { get; set; } = []; - + public HashSet DocumentPaths { get; set; } = []; + [Parameter] - public EventCallback> DocumentPathsChanged { get; set; } - + public EventCallback> DocumentPathsChanged { get; set; } + [Parameter] - public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; + public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; /// /// Catch all documents that are hovered over the AI Studio window and not only over the drop zone. @@ -116,7 +117,7 @@ public partial class AttachDocuments : MSGComponentBase if(!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(path)) continue; - this.DocumentPaths.Add(path); + this.DocumentPaths.Add(FileAttachment.FromPath(path)); } await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); @@ -160,7 +161,7 @@ public partial class AttachDocuments : MSGComponentBase if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(selectedFilePath)) continue; - this.DocumentPaths.Add(selectedFilePath); + this.DocumentPaths.Add(FileAttachment.FromPath(selectedFilePath)); } await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); @@ -199,23 +200,23 @@ public partial class AttachDocuments : MSGComponentBase this.StateHasChanged(); } - private async Task RemoveDocument(string filePath) + private async Task RemoveDocument(FileAttachment fileAttachment) { - this.DocumentPaths.Remove(filePath); - + this.DocumentPaths.Remove(fileAttachment); + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); await this.OnChange(this.DocumentPaths); } /// - /// The user might want to check what we actually extract from his file and therefore give the LLM as an input. + /// The user might want to check what we actually extract from his file and therefore give the LLM as an input. /// - /// The file to check. - private async Task InvestigateFile(string filePath) + /// The file to check. + private async Task InvestigateFile(FileAttachment fileAttachment) { var dialogParameters = new DialogParameters { - { x => x.FilePath, filePath }, + { x => x.FilePath, fileAttachment.FilePath }, }; await this.DialogService.ShowAsync(T("Document Preview"), dialogParameters, DialogOptions.FULLSCREEN); diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs index 2562c7b4..347c096b 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs +++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs @@ -57,7 +57,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable private string currentWorkspaceName = string.Empty; private Guid currentWorkspaceId = Guid.Empty; private CancellationTokenSource? cancellationTokenSource; - private HashSet chatDocumentPaths = []; + private HashSet chatDocumentPaths = []; // Unfortunately, we need the input field reference to blur the focus away. Without // this, we cannot clear the input field. @@ -464,7 +464,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable lastUserPrompt = new ContentText { Text = this.userInput, - FileAttachments = this.chatDocumentPaths.ToList(), + FileAttachments = [..this.chatDocumentPaths.Where(x => x.IsValid)], }; // diff --git a/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor b/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor index 9e8a19f2..3602adf0 100644 --- a/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor +++ b/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor @@ -18,9 +18,9 @@ @{ var currentFolder = string.Empty; - foreach (var filePath in this.DocumentPaths) + foreach (var fileAttachment in this.DocumentPaths) { - var folderPath = Path.GetDirectoryName(filePath); + var folderPath = Path.GetDirectoryName(fileAttachment.FilePath); if (folderPath != currentFolder) { currentFolder = folderPath; @@ -31,8 +31,8 @@ } - - @if (File.Exists(filePath)) + + @if (fileAttachment.Exists) {
@@ -40,7 +40,7 @@ - @Path.GetFileName(filePath) + @fileAttachment.FileName @@ -51,7 +51,7 @@ Color="Color.Error" Class="ml-2" Style="flex-shrink: 0;" - OnClick="@(() => this.DeleteAttachment(filePath))"/> + OnClick="@(() => this.DeleteAttachment(fileAttachment))"/> @@ -64,7 +64,7 @@ - @Path.GetFileName(filePath) + @fileAttachment.FileName @@ -75,7 +75,7 @@ Color="Color.Error" Class="ml-2" Style="flex-shrink: 0;" - OnClick="@(() => this.DeleteAttachment(filePath))"/> + OnClick="@(() => this.DeleteAttachment(fileAttachment))"/> } diff --git a/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor.cs index 64e6bb10..21af5418 100644 --- a/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/ReviewAttachmentsDialog.razor.cs @@ -1,3 +1,4 @@ +using AIStudio.Chat; using AIStudio.Components; using AIStudio.Tools.PluginSystem; @@ -13,20 +14,20 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase private IMudDialogInstance MudDialog { get; set; } = null!; [Parameter] - public HashSet DocumentPaths { get; set; } = new(); - + public HashSet DocumentPaths { get; set; } = new(); + [Inject] private IDialogService DialogService { get; set; } = null!; - + private void Close() => this.MudDialog.Close(DialogResult.Ok(this.DocumentPaths)); - - public static async Task> OpenDialogAsync(IDialogService dialogService, params HashSet documentPaths) + + public static async Task> OpenDialogAsync(IDialogService dialogService, params HashSet documentPaths) { var dialogParameters = new DialogParameters { - { x => x.DocumentPaths, documentPaths } + { x => x.DocumentPaths, documentPaths } }; - + var dialogReference = await dialogService.ShowAsync(TB("Your attached files"), dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) @@ -34,13 +35,13 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase if (dialogResult.Data is null) return documentPaths; - - return dialogResult.Data as HashSet ?? documentPaths; + + return dialogResult.Data as HashSet ?? documentPaths; } - private void DeleteAttachment(string filePath) + private void DeleteAttachment(FileAttachment fileAttachment) { - if (this.DocumentPaths.Remove(filePath)) + if (this.DocumentPaths.Remove(fileAttachment)) { this.StateHasChanged(); } diff --git a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs index a5d6e29d..6b6224aa 100644 --- a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs +++ b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs @@ -54,7 +54,7 @@ public sealed class ProviderAlibabaCloud() : BaseProvider("https://dashscope-int Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index 8a41d0f9..2e82c198 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -44,7 +44,7 @@ public sealed class ProviderAnthropic() : BaseProvider("https://api.anthropic.co Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs index 0f905486..0a9e4181 100644 --- a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs +++ b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs @@ -54,7 +54,7 @@ public sealed class ProviderDeepSeek() : BaseProvider("https://api.deepseek.com/ Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs index daee629d..fa6b229f 100644 --- a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs +++ b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs @@ -54,7 +54,7 @@ public class ProviderFireworks() : BaseProvider("https://api.fireworks.ai/infere Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs index 005d2f74..ae719b49 100644 --- a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs +++ b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs @@ -54,7 +54,7 @@ public sealed class ProviderGWDG() : BaseProvider("https://chat-ai.academiccloud Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs index 98cc49ad..93a9140f 100644 --- a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs +++ b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs @@ -54,7 +54,7 @@ public class ProviderGoogle() : BaseProvider("https://generativelanguage.googlea Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs index c0048379..16453fa9 100644 --- a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs +++ b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs @@ -54,7 +54,7 @@ public class ProviderGroq() : BaseProvider("https://api.groq.com/openai/v1/", LO Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs index 19a204d4..775d0447 100644 --- a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs +++ b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs @@ -54,7 +54,7 @@ public sealed class ProviderHelmholtz() : BaseProvider("https://api.helmholtz-bl Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs index f7c7acbd..67773fcf 100644 --- a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs +++ b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs @@ -59,7 +59,7 @@ public sealed class ProviderHuggingFace : BaseProvider Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs index 8bf55ee0..43c18c89 100644 --- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs +++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs @@ -52,7 +52,7 @@ public sealed class ProviderMistral() : BaseProvider("https://api.mistral.ai/v1/ Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index 7b91a7ae..b0da092d 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -104,7 +104,7 @@ public sealed class ProviderOpenAI() : BaseProvider("https://api.openai.com/v1/" Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs index 0407961e..c0d6550b 100644 --- a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs +++ b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs @@ -57,7 +57,7 @@ public sealed class ProviderOpenRouter() : BaseProvider("https://openrouter.ai/a Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs index 40672460..51a156af 100644 --- a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs +++ b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs @@ -63,7 +63,7 @@ public sealed class ProviderPerplexity() : BaseProvider("https://api.perplexity. Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs index e06e3adc..5b5bda37 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs @@ -50,7 +50,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } }); diff --git a/app/MindWork AI Studio/Provider/X/ProviderX.cs b/app/MindWork AI Studio/Provider/X/ProviderX.cs index 28d01a71..27764c7a 100644 --- a/app/MindWork AI Studio/Provider/X/ProviderX.cs +++ b/app/MindWork AI Studio/Provider/X/ProviderX.cs @@ -54,7 +54,7 @@ public sealed class ProviderX() : BaseProvider("https://api.x.ai/v1/", LOGGER) Content = n.Content switch { - ContentText text => await text.PrepareContentForAI(), + ContentText text => await text.PrepareTextContentForAI(), _ => string.Empty, } });