From 67cde060fbf401391119bdf89ddf9a821d08e09f Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Fri, 18 Sep 2026 16:45:29 +0200 Subject: [PATCH] Name the affected data sources when deleting an embedding provider --- .../Settings/SettingsPanelEmbeddings.razor.cs | 17 +++++--- .../Tools/DataSourceReindexWarning.cs | 40 ++++++++++++++++++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs index d864a6cc..a48b3f7d 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs @@ -133,11 +133,18 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase private async Task DeleteEmbeddingProvider(EmbeddingProvider provider) { - var dialogParameters = new DialogParameters - { - { x => x.Message, string.Format(T("Are you sure you want to delete the embedding provider '{0}'?"), provider.Name) }, - }; - + var question = string.Format(T("Are you sure you want to delete the embedding provider '{0}'?"), provider.Name); + var affectedDataSources = DataSourceReindexWarning.DescribeDataSourcesLosingTheirProvider(this.SettingsManager, provider); + + // + // The names arrive as a Markdown list, so the question travels as Markdown as well as soon + // as there is something to name. With no data source behind the provider, the plain message + // stays what it always was: + // + var dialogParameters = string.IsNullOrEmpty(affectedDataSources) + ? new DialogParameters { { x => x.Message, question } } + : new DialogParameters { { x => x.MarkdownBody, $"{affectedDataSources}{Environment.NewLine}{question}" } }; + var dialogReference = await this.DialogService.ShowAsync(T("Delete Embedding Provider"), dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) diff --git a/app/MindWork AI Studio/Tools/DataSourceReindexWarning.cs b/app/MindWork AI Studio/Tools/DataSourceReindexWarning.cs index 34c4a584..5f8908fd 100644 --- a/app/MindWork AI Studio/Tools/DataSourceReindexWarning.cs +++ b/app/MindWork AI Studio/Tools/DataSourceReindexWarning.cs @@ -8,7 +8,8 @@ using AIStudio.Tools.Services; namespace AIStudio.Tools; /// -/// Asks before an edit makes the prepared documents of data sources useless. +/// Asks before an edit makes the prepared documents of data sources useless, and names the data +/// sources which depend on an embedding provider somebody is about to delete. /// /// /// Kept here rather than in the dialogs which ask -- the embedding provider dialog and the two data @@ -81,6 +82,43 @@ public static class DataSourceReindexWarning return await ConfirmAsync(dialogService, affected, !embeddingProvider.IsSelfHosted); } + /// + /// Names the data sources which would lose their embedding provider, for the deletion question. + /// + /// + /// Deleting is the one case where nothing prepared is thrown away: the documents stay where they + /// are, but nothing can reach them by meaning any more, and nothing new can be prepared either. + /// The names come from the same place as the ones in the questions above so that both lists read + /// alike, which is also why this returns the text instead of asking on its own -- the deletion + /// question has more to say than this. + /// + /// Every data source pointing at the provider is named, prepared or not. A source which was never + /// indexed loses just as much: it can no longer be prepared at all. + /// + /// The settings holding the data sources. + /// The embedding provider which is about to be deleted. + /// The Markdown text, or an empty string when no data source uses that provider. + public static string DescribeDataSourcesLosingTheirProvider(SettingsManager settingsManager, EmbeddingProvider embeddingProvider) + { + if (embeddingProvider == EmbeddingProvider.NONE) + return string.Empty; + + var affected = GetDataSourcesUsing(settingsManager, embeddingProvider.Id).Cast().ToList(); + if (affected.Count == 0) + return string.Empty; + + var body = new StringBuilder(); + + // Counted rather than put into a plural form: the I18N has no mechanism for one. + body.AppendLine(string.Format(TB("These data sources are set up with this embedding provider ({0}):"), affected.Count.CompactCount())); + body.AppendLine(); + body.AppendLine(FormatDataSourceNames(affected)); + body.AppendLine(); + body.AppendLine(TB("They keep answering keyword searches, but searching them by meaning stops working, and no further documents can be prepared for them. The ones which are already prepared stay tied to this provider as well, so you cannot simply move them to another one.")); + + return body.ToString(); + } + /// /// The data sources which are indexed with a given embedding provider. ///