diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
index 17788f24..06009d62 100644
--- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
+++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
@@ -7309,6 +7309,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T29806295
-- Images are not supported at this place
UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T305247150"] = "Images are not supported at this place"
+-- Unsupported file type
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T4041351522"] = "Unsupported file type"
+
-- Executables are not allowed
UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T4167762413"] = "Executables are not allowed"
diff --git a/app/MindWork AI Studio/Chat/ContentText.cs b/app/MindWork AI Studio/Chat/ContentText.cs
index 93d0fcb2..9daeec49 100644
--- a/app/MindWork AI Studio/Chat/ContentText.cs
+++ b/app/MindWork AI Studio/Chat/ContentText.cs
@@ -229,11 +229,15 @@ public sealed class ContentText : IContent
if(this.FileAttachments.Count > 0)
{
+ var normalizedAttachments = this.FileAttachments
+ .Select(attachment => attachment.Normalize())
+ .ToList();
+
// Get the list of existing documents:
- var existingDocuments = this.FileAttachments.Where(x => x.Type is FileAttachmentType.DOCUMENT && x.Exists).ToList();
+ var existingDocuments = normalizedAttachments.Where(x => x.Type is FileAttachmentType.DOCUMENT && x.Exists).ToList();
// Log warning for missing files:
- var missingDocuments = this.FileAttachments.Except(existingDocuments).Where(x => x.Type is FileAttachmentType.DOCUMENT).ToList();
+ var missingDocuments = normalizedAttachments.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);
@@ -269,7 +273,7 @@ public sealed class ContentText : IContent
sb.AppendLine("````");
}
- var numImages = this.FileAttachments.Count(x => x is { IsImage: true, Exists: true });
+ var numImages = normalizedAttachments.Count(x => x is { IsImage: true, Exists: true });
if (numImages > 0)
{
sb.AppendLine();
diff --git a/app/MindWork AI Studio/Chat/FileAttachment.cs b/app/MindWork AI Studio/Chat/FileAttachment.cs
index 10e506d8..bdc9651d 100644
--- a/app/MindWork AI Studio/Chat/FileAttachment.cs
+++ b/app/MindWork AI Studio/Chat/FileAttachment.cs
@@ -53,6 +53,11 @@ public record FileAttachment(FileAttachmentType Type, string FileName, string Fi
///
public bool Exists => File.Exists(this.FilePath);
+ ///
+ /// Rebuilds the attachment from its current file path so file type detection uses the latest rules.
+ ///
+ public FileAttachment Normalize() => FromPath(this.FilePath);
+
///
/// Creates a FileAttachment from a file path by automatically determining the type,
/// extracting the filename, and reading the file size.
diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs
index f734d620..c4b30a2f 100644
--- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs
+++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs
@@ -94,7 +94,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Apply template's file attachments, if any:
foreach (var attachment in this.currentChatTemplate.FileAttachments)
- this.chatDocumentPaths.Add(attachment);
+ this.chatDocumentPaths.Add(attachment.Normalize());
//
// Check for deferred messages of the kind 'SEND_TO_CHAT',
@@ -392,7 +392,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Apply template's file attachments (replaces existing):
this.chatDocumentPaths.Clear();
foreach (var attachment in this.currentChatTemplate.FileAttachments)
- this.chatDocumentPaths.Add(attachment);
+ this.chatDocumentPaths.Add(attachment.Normalize());
if(this.ChatThread is null)
return;
@@ -538,10 +538,15 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
IContent? lastUserPrompt;
if (!reuseLastUserPrompt)
{
+ var normalizedAttachments = this.chatDocumentPaths
+ .Select(attachment => attachment.Normalize())
+ .Where(attachment => attachment.IsValid)
+ .ToList();
+
lastUserPrompt = new ContentText
{
Text = this.userInput,
- FileAttachments = [..this.chatDocumentPaths.Where(x => x.IsValid)],
+ FileAttachments = normalizedAttachments,
};
//
@@ -764,7 +769,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// Apply template's file attachments:
this.chatDocumentPaths.Clear();
foreach (var attachment in this.currentChatTemplate.FileAttachments)
- this.chatDocumentPaths.Add(attachment);
+ this.chatDocumentPaths.Add(attachment.Normalize());
// Now, we have to reset the data source options as well:
this.ApplyStandardDataSourceOptions();
diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
index 0aa16ddf..cbc438cf 100644
--- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
@@ -133,7 +133,7 @@ public partial class ChatTemplateDialog : MSGComponentBase
SystemPrompt = this.DataSystemPrompt,
PredefinedUserPrompt = this.PredefinedUserPrompt,
ExampleConversation = this.dataExampleConversation,
- FileAttachments = [..this.fileAttachments],
+ FileAttachments = this.fileAttachments.Select(attachment => attachment.Normalize()).ToList(),
AllowProfileUsage = this.AllowProfileUsage,
EnterpriseConfigurationPluginId = Guid.Empty,