From ac0dc1e3d72069548aa1a43639422b54c48e7fc3 Mon Sep 17 00:00:00 2001 From: j-erler <35317736+j-erler@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:50:24 +0200 Subject: [PATCH] Fixed chats being deleted without asking (#987) Co-authored-by: Thorsten Sommer --- .../Assistants/I18N/allTexts.lua | 18 ++++---- .../Components/ChatComponent.razor | 2 +- .../Components/ChatComponent.razor.cs | 33 ++++++++----- .../Components/Workspaces.razor.cs | 46 +++++++++---------- .../plugin.lua | 22 ++++----- .../plugin.lua | 18 ++++---- .../Tools/WorkspaceBehaviour.cs | 25 ++++++++-- .../wwwroot/changelog/v26.9.1.md | 1 + 8 files changed, 97 insertions(+), 68 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 2a17926d..1b2d074f 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -3589,6 +3589,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2036185364"] = "Code" -- plus {0} image(s), which is more than the {1} this model accepts UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2059172343"] = "plus {0} image(s), which is more than the {1} this model accepts" +-- Are you sure you want to start a new chat? All unsaved changes will be lost. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2111282488"] = "Are you sure you want to start a new chat? All unsaved changes will be lost." + +-- Unsaved Changes +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2123670756"] = "Unsaved Changes" + +-- Start New Chat +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2310454789"] = "Start New Chat" + -- Italic UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2377171085"] = "Italic" @@ -5281,9 +5290,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T588743762"] = "An error o -- The transcription result is empty. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T974954792"] = "The transcription result is empty." --- Are you sure you want to delete the chat '{0}' in the workspace '{1}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Are you sure you want to delete the chat '{0}' in the workspace '{1}'?" - -- Move chat UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat" @@ -5332,9 +5338,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2151341762"] = "Are you sure -- Are you sure you want to create a another chat? All unsaved changes will be lost. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2237618267"] = "Are you sure you want to create a another chat? All unsaved changes will be lost." --- Delete Chat -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2244038752"] = "Delete Chat" - -- Please enter a chat name. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2301651387"] = "Please enter a chat name." @@ -5344,9 +5347,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2446263209"] = "Workspace Na -- Move to workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2509305748"] = "Move to workspace" --- Are you sure you want to delete the temporary chat '{0}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3043761007"] = "Are you sure you want to delete the temporary chat '{0}'?" - -- Move Chat to Workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3045856778"] = "Move Chat to Workspace" diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor b/app/MindWork AI Studio/Components/ChatComponent.razor index addb3536..ca5566ef 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor +++ b/app/MindWork AI Studio/Components/ChatComponent.razor @@ -92,7 +92,7 @@ @if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) { - + } diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs index 6af7ec72..be2ce136 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs +++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs @@ -1204,10 +1204,10 @@ public partial class ChatComponent : MSGComponentBase { var dialogParameters = new DialogParameters { - { x => x.Message, "Are you sure you want to start a new chat? All unsaved changes will be lost." }, + { x => x.Message, T("Are you sure you want to start a new chat? All unsaved changes will be lost.") }, }; - var dialogReference = await this.DialogService.ShowAsync("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN); + var dialogReference = await this.DialogService.ShowAsync(T("Start New Chat"), dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) return; @@ -1218,16 +1218,27 @@ public partial class ChatComponent : MSGComponentBase // if (this.ChatThread is not null && deletePreviousChat) { - string chatPath; - if (this.ChatThread.WorkspaceId == Guid.Empty) - chatPath = Path.Join(SettingsManager.DataDirectory, "tempChats", this.ChatThread.ChatId.ToString()); + // + // A deleted chat cannot be restored, and the check above never covers this path: it + // exists only while chats are stored automatically, while that check runs only while + // they are stored manually. So we let the deletion itself ask, with the question the + // chat list asks. When it reports the chat is still there, the user declined or the + // chat is busy, and we stop before the reset below takes it out of view: + // + bool chatIsGone; + if (this.Workspaces is null) + chatIsGone = await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, this.ChatThread.WorkspaceId, this.ChatThread.ChatId); else - chatPath = Path.Join(SettingsManager.DataDirectory, "workspaces", this.ChatThread.WorkspaceId.ToString(), this.ChatThread.ChatId.ToString()); + { + var chatPath = this.ChatThread.WorkspaceId == Guid.Empty + ? Path.Join(SettingsManager.DataDirectory, "tempChats", this.ChatThread.ChatId.ToString()) + : Path.Join(SettingsManager.DataDirectory, "workspaces", this.ChatThread.WorkspaceId.ToString(), this.ChatThread.ChatId.ToString()); - if(this.Workspaces is null) - await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, this.ChatThread.WorkspaceId, this.ChatThread.ChatId, askForConfirmation: false); - else - await this.Workspaces.DeleteChatAsync(chatPath, askForConfirmation: false, unloadChat: true); + chatIsGone = await this.Workspaces.DeleteChatAsync(chatPath, unloadChat: true); + } + + if (!chatIsGone) + return; } // @@ -1306,7 +1317,7 @@ public partial class ChatComponent : MSGComponentBase { x => x.Message, T("Are you sure you want to move this chat? All unsaved changes will be lost.") }, }; - var confirmationDialogReference = await this.DialogService.ShowAsync("Unsaved Changes", confirmationDialogParameters, DialogOptions.FULLSCREEN); + var confirmationDialogReference = await this.DialogService.ShowAsync(T("Unsaved Changes"), confirmationDialogParameters, DialogOptions.FULLSCREEN); var confirmationDialogResult = await confirmationDialogReference.Result; if (confirmationDialogResult is null || confirmationDialogResult.Canceled) return; diff --git a/app/MindWork AI Studio/Components/Workspaces.razor.cs b/app/MindWork AI Studio/Components/Workspaces.razor.cs index 05e9c3d9..a3d8c901 100644 --- a/app/MindWork AI Studio/Components/Workspaces.razor.cs +++ b/app/MindWork AI Studio/Components/Workspaces.razor.cs @@ -704,37 +704,35 @@ public partial class Workspaces : MSGComponentBase return null; } - public async Task DeleteChatAsync(string? chatPath, bool askForConfirmation = true, bool unloadChat = true) + /// Deletes the given chat and updates the tree, asking the user to confirm that beforehand. + /// Path of the chat to delete. + /// False skips the question. Only for callers who already asked. + /// Whether to take the chat out of the view when it is the one being shown. + /// True when the chat is gone, which includes it never having been there. False when it is still there. + /// + /// The question itself comes from the workspace behaviour, so that it is worded in one place only. + /// Callers who do more than deleting have to honor the return value: a chat that is busy is not + /// deleted either, and then nothing about it may be reset. + /// + public async Task DeleteChatAsync(string? chatPath, bool askForConfirmation = true, bool unloadChat = true) { var chat = await this.LoadChatAsync(chatPath, false); + + // There is nothing left to delete, so the caller may go on: if (chat is null) - return; + return true; + // + // Deleting a chat while it is being worked on would pull the ground from under that work. + // We check before asking: nobody should confirm something that cannot happen anyway. + // var mediaOwner = MediaImportOwner.ForChat(chat.ChatId); if (this.AIJobService.IsChatGenerationActive(chat.ChatId) || this.MediaTranscriptionService.IsBusy(mediaOwner)) - return; + return false; - if (askForConfirmation) - { - var workspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(chat.WorkspaceId); - var dialogParameters = new DialogParameters - { - { - x => x.Message, (chat.WorkspaceId == Guid.Empty) switch - { - true => string.Format(T("Are you sure you want to delete the temporary chat '{0}'?"), chat.Name), - false => string.Format(T("Are you sure you want to delete the chat '{0}' in the workspace '{1}'?"), chat.Name, workspaceName), - } - }, - }; + if (!await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, chat.WorkspaceId, chat.ChatId, askForConfirmation)) + return false; - var dialogReference = await this.DialogService.ShowAsync(T("Delete Chat"), dialogParameters, DialogOptions.FULLSCREEN); - var dialogResult = await dialogReference.Result; - if (dialogResult is null || dialogResult.Canceled) - return; - } - - await WorkspaceBehaviour.DeleteChatAsync(this.DialogService, chat.WorkspaceId, chat.ChatId, askForConfirmation: false); this.MediaTranscriptionService.ClearOwnerState(mediaOwner); await this.LoadTreeItemsAsync(startPrefetch: false); @@ -743,6 +741,8 @@ public partial class Workspaces : MSGComponentBase this.CurrentChatThread = null; await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread); } + + return true; } private async Task RenameChatAsync(string? chatPath) diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 2392f8b3..453d690a 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -3591,6 +3591,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2036185364"] = "Code" -- plus {0} image(s), which is more than the {1} this model accepts UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2059172343"] = "plus {0} Bild(er), also mehr als die {1}, die dieses Modell akzeptiert" +-- Are you sure you want to start a new chat? All unsaved changes will be lost. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2111282488"] = "Möchten Sie wirklich einen neuen Chat starten? Alle nicht gespeicherten Änderungen gehen verloren." + +-- Unsaved Changes +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2123670756"] = "Nicht gespeicherte Änderungen" + +-- Start New Chat +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2310454789"] = "Neuen Chat starten" + -- Italic UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2377171085"] = "Kursiv" @@ -5283,9 +5292,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T588743762"] = "Während d -- The transcription result is empty. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T974954792"] = "Das Ergebnis der Transkription ist leer." --- Are you sure you want to delete the chat '{0}' in the workspace '{1}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Möchten Sie den Chat „{0}“ im Arbeitsbereich „{1}“ wirklich löschen?" - -- Move chat UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Chat verschieben" @@ -5334,9 +5340,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2151341762"] = "Möchten Sie -- Are you sure you want to create a another chat? All unsaved changes will be lost. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2237618267"] = "Möchten Sie wirklich einen neuen Chat erstellen? Alle nicht gespeicherten Änderungen gehen verloren." --- Delete Chat -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2244038752"] = "Chat löschen" - -- Please enter a chat name. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2301651387"] = "Bitte geben Sie einen Namen für diesen Chat ein." @@ -5346,9 +5349,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2446263209"] = "Name des Arb -- Move to workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2509305748"] = "In einen Arbeitsbereich verschieben" --- Are you sure you want to delete the chat '{0}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3043761007"] = "Sind Sie sicher, dass Sie den Chat „{0}“ löschen möchten?" - -- Move Chat to Workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3045856778"] = "Chat in den Arbeitsbereich verschieben" @@ -12940,7 +12940,7 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::PROVIDERVALIDATION::T649507886"] = UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::PROVIDERVALIDATION::T818893091"] = "Bitte wählen Sie ein Modell aus." -- Are you sure you want to delete the chat '{0}' in the workspace '{1}'? -UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1016188706"] = "Möchten Sie den Chat '{0}' im Arbeitsbereich '{1}' wirklich löschen?" +UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1016188706"] = "Möchten Sie den Chat „{0}“ im Arbeitsbereich „{1}“ wirklich löschen?" -- Unnamed workspace UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unbenannter Arbeitsbereich" @@ -12949,7 +12949,7 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T1307384014"] = "Unbenannt UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T2244038752"] = "Chat löschen" -- Are you sure you want to delete the temporary chat '{0}'? -UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3043761007"] = "Möchten Sie den temporären Chat '{0}' wirklich löschen?" +UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3043761007"] = "Möchten Sie den temporären Chat „{0}“ wirklich löschen?" -- Unnamed chat UI_TEXT_CONTENT["AISTUDIO::TOOLS::WORKSPACEBEHAVIOUR::T3310482275"] = "Unbenannter Chat" diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 41d5692c..1e1ef9ed 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -3591,6 +3591,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2036185364"] = "Code" -- plus {0} image(s), which is more than the {1} this model accepts UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2059172343"] = "plus {0} image(s), which is more than the {1} this model accepts" +-- Are you sure you want to start a new chat? All unsaved changes will be lost. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2111282488"] = "Are you sure you want to start a new chat? All unsaved changes will be lost." + +-- Unsaved Changes +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2123670756"] = "Unsaved Changes" + +-- Start New Chat +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2310454789"] = "Start New Chat" + -- Italic UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2377171085"] = "Italic" @@ -5283,9 +5292,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T588743762"] = "An error o -- The transcription result is empty. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T974954792"] = "The transcription result is empty." --- Are you sure you want to delete the chat '{0}' in the workspace '{1}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1016188706"] = "Are you sure you want to delete the chat '{0}' in the workspace '{1}'?" - -- Move chat UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T1133040906"] = "Move chat" @@ -5334,9 +5340,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2151341762"] = "Are you sure -- Are you sure you want to create a another chat? All unsaved changes will be lost. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2237618267"] = "Are you sure you want to create a another chat? All unsaved changes will be lost." --- Delete Chat -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2244038752"] = "Delete Chat" - -- Please enter a chat name. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2301651387"] = "Please enter a chat name." @@ -5346,9 +5349,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2446263209"] = "Workspace Na -- Move to workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T2509305748"] = "Move to workspace" --- Are you sure you want to delete the chat '{0}'? -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3043761007"] = "Are you sure you want to delete the chat '{0}'?" - -- Move Chat to Workspace UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T3045856778"] = "Move Chat to Workspace" diff --git a/app/MindWork AI Studio/Tools/WorkspaceBehaviour.cs b/app/MindWork AI Studio/Tools/WorkspaceBehaviour.cs index 068f369c..5852a332 100644 --- a/app/MindWork AI Studio/Tools/WorkspaceBehaviour.cs +++ b/app/MindWork AI Studio/Tools/WorkspaceBehaviour.cs @@ -1082,11 +1082,24 @@ public static class WorkspaceBehaviour } } - public static async Task DeleteChatAsync(IDialogService dialogService, Guid workspaceId, Guid chatId, bool askForConfirmation = true) + /// Deletes the given chat, asking the user to confirm that beforehand. + /// Used to show the confirmation. + /// Workspace that owns the chat; an empty id means a temporary chat. + /// Chat to delete. + /// False skips the question. Only for callers who already asked. + /// True when the chat is gone, which includes it never having been there. False when it is still there. + /// + /// This is the one place that asks whether a chat may be deleted, because a deleted chat cannot + /// be restored: there is no trash. Callers who do more than deleting have to honor the return + /// value, or a declined question would still take the rest of their work with it. + /// + public static async Task DeleteChatAsync(IDialogService dialogService, Guid workspaceId, Guid chatId, bool askForConfirmation = true) { var chat = await LoadChatAsync(new(workspaceId, chatId)); + + // There is nothing left to delete, so the caller may go on: if (chat is null) - return; + return true; if (askForConfirmation) { @@ -1105,7 +1118,7 @@ public static class WorkspaceBehaviour var dialogReference = await dialogService.ShowAsync(TB("Delete Chat"), dialogParameters, Dialogs.DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) - return; + return false; } var chatDirectory = chat.WorkspaceId == Guid.Empty @@ -1113,8 +1126,10 @@ public static class WorkspaceBehaviour : Path.Join(SettingsManager.DataDirectory, "workspaces", chat.WorkspaceId.ToString(), chat.ChatId.ToString()); var (acquired, semaphore) = await TryAcquireChatSemaphoreAsync(workspaceId, chatId, nameof(DeleteChatAsync)); + + // Another operation holds the chat, so it stays where it is: if (!acquired) - return; + return false; try { @@ -1128,6 +1143,8 @@ public static class WorkspaceBehaviour semaphore.Release(); ForgetChatSemaphore(workspaceId, chatId); } + + return true; } private static async Task EnsureWorkspace(Guid workspaceId, string workspaceName) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md index 9f01643f..c6cdc326 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md @@ -82,5 +82,6 @@ - Fixed AI Studio asking such a server for its models with an empty key attached when you had stored none at all. Servers behind a login turn those requests down. - Fixed a key that could not be saved going unmentioned for the servers you host yourself. You are now told what went wrong, instead of the settings simply staying open. - Fixed transcripts quietly losing what was said softly, such as a greeting at the very beginning of a recording. AI Studio compressed recordings so far before sending them to your transcription provider that the model could no longer make out those passages. Recordings now keep enough details for the whole of what you said to arrive. +- Fixed the button in the chat toolbar that deletes the current chat and starts a new one doing so without asking. It now asks for your confirmation first, just like the chat list does, because a deleted chat cannot be brought back. The button shows a delete icon in red now, instead of one that looked like a reload. - Upgraded the Visual Briefing assistant (in preview) from the prototype to the beta state. The assistant is now completely implemented and is undergoing a deeper testing phase in preparation for release. To try it, open the app settings, allow preview features down to beta, and then enable the Visual Briefing assistant there. - Upgraded the vector database behind local RAG (Qdrant Edge) to version 0.8.0.