diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor
index 4b68618a..ec801e84 100644
--- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor
+++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor
@@ -103,7 +103,7 @@ else
@T("Documents for the analysis")
-
+
diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
index a647876e..bddcbe43 100644
--- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
+++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
@@ -36,6 +36,9 @@ public partial class AttachDocuments : MSGComponentBase
[Parameter]
public bool UseSmallForm { get; set; }
+ [Parameter]
+ public AIStudio.Settings.Provider? Provider { get; set; }
+
[Inject]
private ILogger Logger { get; set; } = null!;
@@ -114,7 +117,7 @@ public partial class AttachDocuments : MSGComponentBase
foreach (var path in paths)
{
- if(!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(path))
+ if(!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(FileExtensionValidation.UseCase.ATTACHING_CONTENT, path, this.Provider))
continue;
this.DocumentPaths.Add(FileAttachment.FromPath(path));
@@ -158,7 +161,7 @@ public partial class AttachDocuments : MSGComponentBase
if (!File.Exists(selectedFilePath))
continue;
- if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(selectedFilePath))
+ if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(FileExtensionValidation.UseCase.ATTACHING_CONTENT, selectedFilePath, this.Provider))
continue;
this.DocumentPaths.Add(FileAttachment.FromPath(selectedFilePath));
diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor b/app/MindWork AI Studio/Components/ChatComponent.razor
index 8f4eca23..1eb28244 100644
--- a/app/MindWork AI Studio/Components/ChatComponent.razor
+++ b/app/MindWork AI Studio/Components/ChatComponent.razor
@@ -83,7 +83,7 @@
-
+
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
{
diff --git a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs
index cd970cd4..5db85e21 100644
--- a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs
+++ b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs
@@ -55,7 +55,7 @@ public partial class ReadFileContent : MSGComponentBase
return;
}
- if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(selectedFile.SelectedFilePath))
+ if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(FileExtensionValidation.UseCase.DIRECTLY_LOADING_CONTENT, selectedFile.SelectedFilePath))
{
this.Logger.LogWarning("User attempted to load unsupported file: {FilePath}", selectedFile.SelectedFilePath);
return;
diff --git a/app/MindWork AI Studio/Tools/Validation/FileExtensionValidation.cs b/app/MindWork AI Studio/Tools/Validation/FileExtensionValidation.cs
index 8be34eca..991dcbdf 100644
--- a/app/MindWork AI Studio/Tools/Validation/FileExtensionValidation.cs
+++ b/app/MindWork AI Studio/Tools/Validation/FileExtensionValidation.cs
@@ -1,3 +1,5 @@
+using AIStudio.Provider;
+using AIStudio.Settings;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.Rust;
@@ -10,12 +12,35 @@ public static class FileExtensionValidation
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(FileExtensionValidation).Namespace, nameof(FileExtensionValidation));
+ ///
+ /// Defines the use cases for file extension validation.
+ ///
+ public enum UseCase
+ {
+ ///
+ /// No specific use case; general validation.
+ ///
+ NONE,
+
+ ///
+ /// Validating for directly loading content into the UI. In this state, there might be no provider selected yet.
+ ///
+ DIRECTLY_LOADING_CONTENT,
+
+ ///
+ /// Validating for attaching content to a message or prompt.
+ ///
+ ATTACHING_CONTENT,
+ }
+
///
/// Validates the file extension and sends appropriate MessageBus notifications when invalid.
///
+ /// The validation use case.
/// The file path to validate.
+ /// The selected provider.
/// True if valid, false if invalid (error/warning already sent via MessageBus).
- public static async Task IsExtensionValidWithNotifyAsync(string filePath)
+ public static async Task IsExtensionValidWithNotifyAsync(UseCase useCae, string filePath, Settings.Provider? provider = null)
{
var ext = Path.GetExtension(filePath).TrimStart('.').ToLowerInvariant();
if(FileTypeFilter.Executables.FilterExtensions.Contains(ext))
@@ -26,12 +51,36 @@ public static class FileExtensionValidation
return false;
}
- if(FileTypeFilter.AllImages.FilterExtensions.Contains(ext))
+ var capabilities = provider?.GetModelCapabilities() ?? new();
+ if (FileTypeFilter.AllImages.FilterExtensions.Contains(ext))
{
- await MessageBus.INSTANCE.SendWarning(new(
- Icons.Material.Filled.ImageNotSupported,
- TB("Images are not supported yet")));
- return false;
+ switch (useCae)
+ {
+ // In this use case, we cannot guarantee that a provider is selected yet:
+ case UseCase.DIRECTLY_LOADING_CONTENT:
+ await MessageBus.INSTANCE.SendWarning(new(
+ Icons.Material.Filled.ImageNotSupported,
+ TB("Images are not supported at this place")));
+ return false;
+
+ // In this use case, we can check the provider capabilities:
+ case UseCase.ATTACHING_CONTENT when capabilities.Contains(Capability.SINGLE_IMAGE_INPUT) ||
+ capabilities.Contains(Capability.MULTIPLE_IMAGE_INPUT):
+ return true;
+
+ // We know that images are not supported:
+ case UseCase.ATTACHING_CONTENT:
+ await MessageBus.INSTANCE.SendWarning(new(
+ Icons.Material.Filled.ImageNotSupported,
+ TB("Images are not supported by the selected provider and model")));
+ return false;
+
+ default:
+ await MessageBus.INSTANCE.SendWarning(new(
+ Icons.Material.Filled.ImageNotSupported,
+ TB("Images are not supported yet")));
+ return false;
+ }
}
if(FileTypeFilter.AllVideos.FilterExtensions.Contains(ext))