From 9bdee942b4c01b461286e4833a8be5572f56fbee Mon Sep 17 00:00:00 2001 From: hart_s3 Date: Tue, 5 May 2026 14:22:36 +0200 Subject: [PATCH] Added "No provider" option --- .../DocumentAnalysisAssistant.razor.cs | 11 ++++- .../Assistants/I18N/allTexts.lua | 3 ++ .../ConfigurationProviderSelection.razor.cs | 10 +++-- .../plugin.lua | 3 ++ .../plugin.lua | 3 ++ app/MindWork AI Studio/Settings/Provider.cs | 4 ++ .../Settings/SettingsManager.cs | 10 ++++- .../Tools/ComponentsExtensions.cs | 42 +++++++++++++++++++ .../wwwroot/changelog/v26.4.1.md | 1 + 9 files changed, 82 insertions(+), 5 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 77522cd8d..a2b87a98f 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -417,6 +417,13 @@ private void ApplyPolicyPreselection(bool preferPolicyPreselection = false) } // Try to apply the policy preselection: + if (Settings.Provider.IsNoProviderPreselection(this.selectedPolicy.PreselectedProvider)) + { + this.ProviderSettings = Settings.Provider.NONE; + this.CurrentProfile = this.ResolveProfileSelection(); + return; + } + var policyProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.selectedPolicy.PreselectedProvider); if (policyProvider is not null && policyProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel) { @@ -763,7 +770,9 @@ private string GenerateLuaPolicyExport() ["MinimumProviderConfidence"] = "{{this.selectedPolicy.MinimumProviderConfidence}}", -- Optional: preselect a provider or profile by ID. - -- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"]. + -- Use an empty provider ID to fall back to the app default provider. + -- Use "{{Settings.Provider.NO_PROVIDER_PRESELECTION_ID}}" to explicitly preselect no provider. + -- Any other IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"]. ["PreselectedProvider"] = "{{preselectedProvider}}", ["PreselectedProfile"] = "{{preselectedProfile}}", diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 07569e094..39e419657 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -2191,6 +2191,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218 -- Use app default UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "Use app default" +-- No provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "No provider" + -- No shortcut configured UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "No shortcut configured" diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs index 8267219c0..e9d7bd23b 100644 --- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs +++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs @@ -4,6 +4,7 @@ using AIStudio.Settings; using AIStudio.Tools.PluginSystem; using Microsoft.AspNetCore.Components; +using SettingsProvider = AIStudio.Settings.Provider; namespace AIStudio.Components; @@ -38,8 +39,11 @@ public partial class ConfigurationProviderSelection : MSGComponentBase [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")] private IEnumerable> FilteredData() { - if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS) + if(this.Component.SupportsAppDefaultProviderSelection()) + { yield return new(T("Use app default"), string.Empty); + yield return new(T("No provider"), SettingsProvider.NO_PROVIDER_PRESELECTION_ID); + } // Get the minimum confidence level for this component, and/or the enforced global minimum confidence level: var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.Component); @@ -68,11 +72,11 @@ private IEnumerable> FilteredData() { case Event.CONFIGURATION_CHANGED: - if(string.IsNullOrWhiteSpace(this.SelectedValue())) + if(string.IsNullOrWhiteSpace(this.SelectedValue()) || SettingsProvider.IsNoProviderPreselection(this.SelectedValue())) break; // Check if the selected value is still valid: - if (this.Data.All(x => x.Value != this.SelectedValue())) + if (this.FilteredData().All(x => x.Value != this.SelectedValue())) { this.SelectedValue = () => string.Empty; this.SelectionUpdate(string.Empty); 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 b65b6552b..2dbe9520e 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 @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218 -- Use app default UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "App-Standard verwenden" +-- No provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "Kein Anbieter" + -- No shortcut configured UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "Keinen Tastaturkurzbefehl konfiguriert" 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 434c6aa31..25a1fdcf4 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 @@ -2193,6 +2193,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T20906218 -- Use app default UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3672477670"] = "Use app default" +-- No provider +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONPROVIDERSELECTION::T3740605451"] = "No provider" + -- No shortcut configured UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CONFIGURATIONSHORTCUT::T3099115336"] = "No shortcut configured" diff --git a/app/MindWork AI Studio/Settings/Provider.cs b/app/MindWork AI Studio/Settings/Provider.cs index 0ccf272cf..121019cb5 100644 --- a/app/MindWork AI Studio/Settings/Provider.cs +++ b/app/MindWork AI Studio/Settings/Provider.cs @@ -36,6 +36,8 @@ public sealed record Provider( { private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(); + public const string NO_PROVIDER_PRESELECTION_ID = "__NO_PROVIDER__"; + public static readonly Provider NONE = new(); public Provider() : this( @@ -66,6 +68,8 @@ public override string ToString() } #endregion + + public static bool IsNoProviderPreselection(string? providerId) => providerId == NO_PROVIDER_PRESELECTION_ID; #region Implementation of ISecretId diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 3ec8906cc..88f8274a6 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -256,9 +256,10 @@ private static string GetPrimaryLanguage(string localeTag) public Provider GetPreselectedProvider(Tools.Components component, string? currentProviderId = null, bool usePreselectionBeforeCurrentProvider = false) { var minimumLevel = this.GetMinimumConfidenceLevel(component); + var hasExplicitNoProviderPreselection = component.HasExplicitNoProviderPreselection(this); // When there is only one provider, and it has a confidence level that is high enough, we return it: - if (this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel) + if (!hasExplicitNoProviderPreselection && this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel) return this.ConfigurationData.Providers[0]; // Is there a current provider with a sufficiently high confidence level? @@ -290,6 +291,9 @@ public Provider GetPreselectedProvider(Tools.Components component, string? curre // if(currentProvider != Provider.NONE) return currentProvider; + + if (hasExplicitNoProviderPreselection) + return Provider.NONE; // // Case: The current provider should be used before the preselected provider, @@ -308,6 +312,7 @@ public Provider GetPreselectedProvider(Tools.Components component, string? curre public Provider GetChatProviderForLoadedChat(string? chatProviderId = null) { var minimumLevel = this.GetMinimumConfidenceLevel(Tools.Components.CHAT); + var hasExplicitNoChatProviderPreselection = Tools.Components.CHAT.HasExplicitNoProviderPreselection(this); bool IsSelectableProvider(Provider provider) => provider != Provider.NONE @@ -333,6 +338,9 @@ bool IsSelectableProvider(Provider provider) => if (defaultChatProvider is not null) return defaultChatProvider; + if (hasExplicitNoChatProviderPreselection) + return Provider.NONE; + var defaultAppProvider = FindProviderById(this.ConfigurationData.App.PreselectedProvider); if (defaultAppProvider is not null) return defaultAppProvider; diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index bd48dbc5b..7fcc13cf7 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -8,6 +8,17 @@ namespace AIStudio.Tools; public static class ComponentsExtensions { private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ComponentsExtensions).Namespace, nameof(ComponentsExtensions)); + + public static bool SupportsAppDefaultProviderSelection(this Components component) => component switch + { + Components.NONE => false, + Components.APP_SETTINGS => false, + Components.AGENT_TEXT_CONTENT_CLEANER => false, + Components.AGENT_DATA_SOURCE_SELECTION => false, + Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => false, + Components.AGENT_ASSISTANT_PLUGIN_AUDIT => false, + _ => true, + }; public static bool AllowSendTo(this Components component) => component switch { @@ -103,9 +114,40 @@ public static class ComponentsExtensions _ => default, }; + public static bool HasExplicitNoProviderPreselection(this Components component, SettingsManager settingsManager) + { + var preselectedProviderId = component switch + { + Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider : string.Empty, + Components.ICON_FINDER_ASSISTANT => settingsManager.ConfigurationData.IconFinder.PreselectOptions ? settingsManager.ConfigurationData.IconFinder.PreselectedProvider : string.Empty, + Components.REWRITE_ASSISTANT => settingsManager.ConfigurationData.RewriteImprove.PreselectOptions ? settingsManager.ConfigurationData.RewriteImprove.PreselectedProvider : string.Empty, + Components.PROMPT_OPTIMIZER_ASSISTANT => settingsManager.ConfigurationData.PromptOptimizer.PreselectOptions ? settingsManager.ConfigurationData.PromptOptimizer.PreselectedProvider : string.Empty, + Components.TRANSLATION_ASSISTANT => settingsManager.ConfigurationData.Translation.PreselectOptions ? settingsManager.ConfigurationData.Translation.PreselectedProvider : string.Empty, + Components.AGENDA_ASSISTANT => settingsManager.ConfigurationData.Agenda.PreselectOptions ? settingsManager.ConfigurationData.Agenda.PreselectedProvider : string.Empty, + Components.CODING_ASSISTANT => settingsManager.ConfigurationData.Coding.PreselectOptions ? settingsManager.ConfigurationData.Coding.PreselectedProvider : string.Empty, + Components.TEXT_SUMMARIZER_ASSISTANT => settingsManager.ConfigurationData.TextSummarizer.PreselectOptions ? settingsManager.ConfigurationData.TextSummarizer.PreselectedProvider : string.Empty, + Components.EMAIL_ASSISTANT => settingsManager.ConfigurationData.EMail.PreselectOptions ? settingsManager.ConfigurationData.EMail.PreselectedProvider : string.Empty, + Components.LEGAL_CHECK_ASSISTANT => settingsManager.ConfigurationData.LegalCheck.PreselectOptions ? settingsManager.ConfigurationData.LegalCheck.PreselectedProvider : string.Empty, + Components.SYNONYMS_ASSISTANT => settingsManager.ConfigurationData.Synonyms.PreselectOptions ? settingsManager.ConfigurationData.Synonyms.PreselectedProvider : string.Empty, + Components.MY_TASKS_ASSISTANT => settingsManager.ConfigurationData.MyTasks.PreselectOptions ? settingsManager.ConfigurationData.MyTasks.PreselectedProvider : string.Empty, + Components.JOB_POSTING_ASSISTANT => settingsManager.ConfigurationData.JobPostings.PreselectOptions ? settingsManager.ConfigurationData.JobPostings.PreselectedProvider : string.Empty, + Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider : string.Empty, + Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.ERI.PreselectedProvider : string.Empty, + Components.I18N_ASSISTANT => settingsManager.ConfigurationData.I18N.PreselectOptions ? settingsManager.ConfigurationData.I18N.PreselectedProvider : string.Empty, + Components.SLIDE_BUILDER_ASSISTANT => settingsManager.ConfigurationData.SlideBuilder.PreselectOptions ? settingsManager.ConfigurationData.SlideBuilder.PreselectedProvider : string.Empty, + Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Chat.PreselectedProvider : string.Empty, + _ => string.Empty, + }; + + return Settings.Provider.IsNoProviderPreselection(preselectedProviderId); + } + [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")] public static AIStudio.Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager) { + if (component.HasExplicitNoProviderPreselection(settingsManager)) + return Settings.Provider.NONE; + var preselectedProvider = component switch { Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : null, diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.4.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.4.1.md index 3ff00c6ab..8506390aa 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.4.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.4.1.md @@ -10,6 +10,7 @@ - Added pre-call validation to check if the selected model exists for the provider before making the request. - Added math rendering in chats for LaTeX display formulas, including block formats such as `$$ ... $$` and `\[ ... \]`. - Added support for mandatory information notices in configuration plugins. Organizations can now require users to read and confirm important information before continuing in AI Studio. +- Added "No provider" option in the internal settings of chat and assistants - Released the document analysis assistant after an intense testing phase. - Improved enterprise deployment for organizations: administrators can now provide up to 10 centrally managed enterprise configuration slots, use policy files on Linux and macOS, and continue using older configuration formats as a fallback during migration. - Improved transparency on the information page by showing configured mandatory notices together with their source and confirmation status.