diff --git a/app/MindWork AI Studio/Dialogs/AssistantPluginAuditDialog.razor.cs b/app/MindWork AI Studio/Dialogs/AssistantPluginAuditDialog.razor.cs index 19f6b0ed..42401df4 100644 --- a/app/MindWork AI Studio/Dialogs/AssistantPluginAuditDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/AssistantPluginAuditDialog.razor.cs @@ -74,11 +74,26 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase 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; + /// + /// The audit result this dialog acts on: the one it has, unless that one concluded nothing. + /// + /// + /// UNKNOWN is not a low audit level, it is the absence of a result: the model was unreachable, + /// the key was wrong, no provider was trusted enough. Everything which decides something has to + /// read it as no audit at all -- whether the plugin may be activated, and what this dialog hands + /// back to be stored. Otherwise a check which failed would unlock a plugin nobody has checked, + /// and storing it would replace the last result which did say something, because audits are kept + /// one per plugin. This is the rule PluginAssistantSecurityResolver already applies to the stored + /// audits. What the dialog shows the user still reads the raw result: a failed run is precisely + /// what they need to see. + /// + private PluginAssistantAudit? ConclusiveAudit => this.audit is { Level: not AssistantAuditLevel.UNKNOWN } ? this.audit : null; - private bool IsActivationBlockedBySettings => this.AuditSettings.RequireAuditBeforeActivation && (this.audit is null || this.IsAuditBelowMinimum && this.AuditSettings.BlockActivationBelowMinimum); + private bool IsAuditBelowMinimum => this.ConclusiveAudit is not null && this.ConclusiveAudit.Level < this.MinimumLevel; - private bool RequiresActivationConfirmation => this.audit is not null && this.IsAuditBelowMinimum && !this.IsActivationBlockedBySettings; + private bool IsActivationBlockedBySettings => this.AuditSettings.RequireAuditBeforeActivation && (this.ConclusiveAudit is null || this.IsAuditBelowMinimum && this.AuditSettings.BlockActivationBelowMinimum); + + private bool RequiresActivationConfirmation => this.ConclusiveAudit is not null && this.IsAuditBelowMinimum && !this.IsActivationBlockedBySettings; private bool CanEnablePlugin => this.plugin is not null && !this.isAuditing && !this.IsActivationBlockedBySettings; @@ -88,10 +103,9 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase /// Whether this dialog has produced an audit result, which is why it offers no second run. /// /// - /// Set only for a result worth keeping. An audit which ended in UNKNOWN answered nothing about - /// the plugin: the model was unreachable, the key was wrong, no provider was trusted enough. - /// Locking the button on that would leave the user in front of a plugin they cannot check and - /// cannot enable, with closing and reopening the dialog as the only way on. + /// A run which concluded nothing must not set this. It would leave the user in front of a plugin + /// they cannot check and cannot enable, with closing and reopening the dialog as the only way on + /// -- and a failed run is the one case where trying again is exactly the right thing to do. /// private bool justAudited; @@ -139,7 +153,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase finally { this.isAuditing = false; - this.justAudited = this.audit is { Level: not AssistantAuditLevel.UNKNOWN }; + this.justAudited = this.ConclusiveAudit is not null; await this.InvokeAsync(this.StateHasChanged); } } @@ -154,13 +168,13 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase private void CloseWithoutActivation() { - if (this.audit is null) + if (this.ConclusiveAudit is null) { this.MudDialog.Cancel(); return; } - this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.audit, false))); + this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.ConclusiveAudit, false))); } private async Task EnablePlugin() @@ -174,7 +188,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase if (this.RequiresActivationConfirmation && !await this.ConfirmActivationBelowMinimumAsync()) return; - this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.audit, true))); + this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.ConclusiveAudit, true))); } private async Task ConfirmActivationBelowMinimumAsync()