Offer a model in the security audit dialog when none is configured

This commit is contained in:
Thorsten Sommer 2026-09-19 19:43:18 +02:00
parent 1379ff6aab
commit 8f9d289973
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
2 changed files with 51 additions and 5 deletions

View File

@ -36,6 +36,18 @@
</MudText>
</MudPaper>
@if (this.NeedsProviderSelection && !this.securityState.IsEnterpriseApproved)
{
<MudPaper Class="pa-3 border-dashed border rounded-lg">
<MudText Typo="Typo.body2" Class="mb-3">
@T("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.")
</MudText>
<CascadingValue Value="Components.AGENT_ASSISTANT_PLUGIN_AUDIT">
<ProviderSelection @bind-ProviderSettings="@this.auditProviderSelection" ValidateProvider="@this.ValidatingProvider" Disabled="@this.isAuditing" />
</CascadingValue>
</MudPaper>
}
<MudExpansionPanels MultiExpansion="true">
<MudExpansionPanel Expanded="true">
<TitleContent>

View File

@ -39,11 +39,32 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
private bool isAuditing;
private PluginAssistantSecurityState securityState = new();
/// <summary>
/// The provider the user picks inside this dialog when nothing is configured for the audit agent.
/// </summary>
/// <remarks>
/// It lives and dies with this dialog and is never written to the settings: an audit is a one-off
/// job, and the choice made here says nothing about which model the next one should use.
/// </remarks>
private AIStudio.Settings.Provider auditProviderSelection = AIStudio.Settings.Provider.NONE;
private AIStudio.Settings.Provider CurrentProvider => this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT, null, true);
private string ProviderLabel => this.CurrentProvider == AIStudio.Settings.Provider.NONE
? this.T("No provider configured")
: $"{this.CurrentProvider.InstanceName} ({this.CurrentProvider.UsedLLMProvider.ToName()})";
/// <summary>
/// The provider this audit runs with: the configured one, or what the user picked here instead.
/// </summary>
private AIStudio.Settings.Provider EffectiveProvider => this.CurrentProvider == AIStudio.Settings.Provider.NONE
? this.auditProviderSelection
: this.CurrentProvider;
/// <summary>
/// Whether this dialog has to offer a provider, because neither the audit agent nor the app has one.
/// </summary>
private bool NeedsProviderSelection => this.CurrentProvider == AIStudio.Settings.Provider.NONE;
private string ProviderLabel => this.EffectiveProvider == AIStudio.Settings.Provider.NONE
? T("No provider configured")
: $"{this.EffectiveProvider.InstanceName} ({this.EffectiveProvider.UsedLLMProvider.ToName()})";
private DataAssistantPluginAudit AuditSettings => this.SettingsManager.ConfigurationData.AssistantPluginAudit;
@ -51,7 +72,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
private string MinimumLevelLabel => this.MinimumLevel.GetName();
private bool CanRunAudit => this.plugin is not null && this.CurrentProvider != AIStudio.Settings.Provider.NONE && !this.isAuditing && !this.securityState.IsEnterpriseApproved;
private bool CanRunAudit => this.plugin is not null && this.EffectiveProvider != AIStudio.Settings.Provider.NONE && !this.isAuditing && !this.securityState.IsEnterpriseApproved;
private bool IsAuditBelowMinimum => this.audit is not null && this.audit.Level < this.MinimumLevel;
@ -97,7 +118,12 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
try
{
this.audit = await this.AssistantPluginAuditService.RunAuditAsync(this.plugin);
//
// The provider picked here is handed over as the fallback: the audit service uses it only
// when nothing is configured for the audit agent, so an organization-wide provider keeps
// its precedence.
//
this.audit = await this.AssistantPluginAuditService.RunAuditAsync(this.plugin, fallbackProvider: this.auditProviderSelection);
this.securityState = PluginAssistantSecurityResolver.Resolve(this.SettingsManager, this.plugin);
}
finally
@ -108,6 +134,14 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
}
}
private string? ValidatingProvider(AIStudio.Settings.Provider provider)
{
if (provider.UsedLLMProvider == LLMProviders.NONE)
return T("Please select a provider.");
return null;
}
private void CloseWithoutActivation()
{
if (this.audit is null)