diff --git a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs index 0fd6fef8..aa1e600f 100644 --- a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs +++ b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs @@ -124,12 +124,19 @@ public sealed class AssistantAuditAgent(ILogger logger, ILo /// Resolves and stores the provider configuration used for assistant plugin audits. /// /// The provider to use when no provider is configured for the audit agent. - /// The configured provider, or when no audit provider is configured. + /// The configured provider, or Provider.NONE when no audit provider is configured. + /// + /// A fallback is a provider somebody picked for something else: the assistant they were building, + /// the revision they asked for, the check they are standing in front of. Whether it may read a + /// plugin's source and its Lua files is decided by what this agent requires, not by what it was + /// picked under, so it has to clear this agent's confidence bar before it is used. Otherwise a + /// provider an organization ruled out for audits would see the very thing it was ruled out for. + /// public AIStudio.Settings.Provider ResolveProvider(AIStudio.Settings.Provider? fallbackProvider = null) { var provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT, null, true); - if (provider == AIStudio.Settings.Provider.NONE && fallbackProvider is not null) - provider = fallbackProvider; + if (provider == AIStudio.Settings.Provider.NONE && fallbackProvider is { } candidate && this.SettingsManager.IsProviderConfident(candidate, Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT)) + provider = candidate; this.ProviderSettings = provider; return provider; @@ -149,12 +156,24 @@ public sealed class AssistantAuditAgent(ILogger logger, ILo var provider = this.ResolveProvider(fallbackProvider); if (provider == AIStudio.Settings.Provider.NONE) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, string.Format(TB("No provider is configured for the Security Audit Agent.")))); + // + // There are two ways to end up here, and they send the user to different places: nobody + // named a provider, or the one at hand is not trusted enough for an audit. Saying that + // none is configured while one sits right there would send them looking in vain. + // + var wasFallbackRejected = fallbackProvider is { UsedLLMProvider: not LLMProviders.NONE }; + var message = wasFallbackRejected + ? TB("The selected provider is not trusted enough for security checks. Pick one which meets the confidence required here, or choose a dedicated provider for security checks in the app settings.") + : TB("No provider is configured for the Security Audit Agent."); + + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, message)); return new AssistantAuditResult { Level = nameof(AssistantAuditLevel.UNKNOWN), - Summary = TB("No audit provider is configured."), + Summary = wasFallbackRejected + ? TB("The provider is not trusted enough for security checks.") + : TB("No audit provider is configured."), }; } diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 160e7f85..d3ea7596 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -52,12 +52,18 @@ UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2034826 -- The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later. UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2451573087"] = "The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later." +-- The provider is not trusted enough for security checks. +UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2861409367"] = "The provider is not trusted enough for security checks." + -- The audit agent did not return a usable response. UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T3310188890"] = "The audit agent did not return a usable response." -- No provider is configured for the Security Audit Agent. UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T3605554201"] = "No provider is configured for the Security Audit Agent." +-- The selected provider is not trusted enough for security checks. Pick one which meets the confidence required here, or choose a dedicated provider for security checks in the app settings. +UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T4104574219"] = "The selected provider is not trusted enough for security checks. Pick one which meets the confidence required here, or choose a dedicated provider for security checks in the app settings." + -- The audit result was empty. UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T432419958"] = "The audit result was empty." @@ -4291,15 +4297,18 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T3980535867"] = "Please -- Attached file '{0}'. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T853724151"] = "Attached file '{0}'." +-- The selected model does not meet the confidence requirements of the content cleaner. Please select another model, or configure an eligible one in the app settings. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1028731446"] = "The selected model does not meet the confidence requirements of the content cleaner. Please select another model, or configure an eligible one in the app settings." + +-- The content cleaner uses the model of this assistant. Please select one below. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1160768613"] = "The content cleaner uses the model of this assistant. Please select one below." + -- The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1164201762"] = "The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used." -- Fetch UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T1396322691"] = "Fetch" --- Please select a provider to use the cleanup agent. -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T2035652317"] = "Please select a provider to use the cleanup agent." - -- Please provide a URL to load the content from. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T2235427807"] = "Please provide a URL to load the content from." @@ -4333,6 +4342,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T3825586228"] = "Please p -- Show web content options UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T4249712357"] = "Show web content options" +-- The content was loaded, but not cleaned: no model is available for the content cleaner. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENT::T903778235"] = "The content was loaded, but not cleaned: no model is available for the content cleaner." + -- Loading UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READWEBCONTENTSTEPSEXTENSIONS::T1404011351"] = "Loading" @@ -5422,9 +5434,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1357418474"] = -- No security issues were found during this check. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1423034104"] = "No security issues were found during this check." --- No provider configured -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1476185409"] = "No provider configured" - -- {0:0.##} KB UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T14914764"] = "{0:0.##} KB" @@ -5464,6 +5473,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1996966820"] = -- Properties UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2177370620"] = "Properties" +-- Model +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2189814010"] = "Model" + -- Items: {0} UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2204150657"] = "Items: {0}" @@ -5473,12 +5485,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2562655035"] = -- The assistant plugin could not be resolved for auditing. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "The assistant plugin could not be resolved for auditing." --- Audit provider -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2757790517"] = "Audit provider" - -- Size UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2789707388"] = "Size" +-- No model configured +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2941224401"] = "No model configured" + -- Prompt: set UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3156437951"] = "Prompt: set" @@ -5527,6 +5539,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T4229995215"] = -- The assistant plugin '{0}' was audited with the level '{1}', which is below the required safety level '{2}'. Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T521056824"] = "The assistant plugin '{0}' was audited with the level '{1}', which is below the required safety level '{2}'. Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?" +-- Audit model +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T532102309"] = "Audit model" + +-- No model is set for security checks, neither for this agent nor for the app as a whole. Choose one here to check this plugin. Your choice applies to this check only; you can set a permanent one in the app settings. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T614645381"] = "No model is set for security checks, neither for this agent nor for the app as a whole. Choose one here to check this plugin. Your choice applies to this check only; you can set a permanent one in the app settings." + -- System Prompt UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T628396066"] = "System Prompt" @@ -5539,6 +5557,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T760494712"] = " -- Start Security Check UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T811648299"] = "Start Security Check" +-- Please select a model. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T818893091"] = "Please select a model." + -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T900713019"] = "Cancel" diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor b/app/MindWork AI Studio/Components/ProviderSelection.razor index f1fab87d..d6122c01 100644 --- a/app/MindWork AI Studio/Components/ProviderSelection.razor +++ b/app/MindWork AI Studio/Components/ProviderSelection.razor @@ -3,7 +3,7 @@ @{ var availableProviderItems = this.GetAvailableProviderSelectionItems().ToList(); } - + @foreach (var providerItem in availableProviderItems) { diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs index b40175f6..718a8ff6 100644 --- a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs +++ b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs @@ -19,6 +19,17 @@ public partial class ProviderSelection : MSGComponentBase [Parameter] public Func ValidateProvider { get; set; } = _ => null; + /// + /// What this place calls the thing being picked, when "Provider" is not the word it uses. + /// + /// + /// Some places have the user pick a provider in order to set it up, and there the word is right. + /// Others have them pick one to get a job done, and speak of the model throughout. A field + /// labelled "Provider" in the middle of such a text reads like a second, different choice. + /// + [Parameter] + public string? Label { get; set; } + /// /// Gets or sets whether provider selection is disabled. /// diff --git a/app/MindWork AI Studio/Components/ReadWebContent.razor b/app/MindWork AI Studio/Components/ReadWebContent.razor index 10ebc52d..0a5bb3d0 100644 --- a/app/MindWork AI Studio/Components/ReadWebContent.razor +++ b/app/MindWork AI Studio/Components/ReadWebContent.razor @@ -3,7 +3,13 @@ @if (this.Preselect) { - + + @if (this.ContentCleanerHint is { } contentCleanerHint) + { + + @contentCleanerHint + + }