diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor index 20fe7778..108f7375 100644 --- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor +++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor @@ -6,7 +6,7 @@ @* ReSharper disable once CSharpWarnings::CS8974 *@ - + @foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders))) { @provider @@ -26,7 +26,7 @@ AdornmentIcon="@Icons.Material.Filled.VpnKey" AdornmentColor="Color.Info" InputType="InputType.Password" - Validation="@this.ValidatingAPIKey" + Validation="@this.providerValidation.ValidatingAPIKey" /> - + @foreach (Host host in Enum.GetValues(typeof(Host))) { @host.Name() @@ -68,7 +68,7 @@ else { Load - + @foreach (var model in this.availableModels) { @model @@ -89,7 +89,7 @@ Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Lightbulb" AdornmentColor="Color.Info" - Validation="@this.ValidatingInstanceName" + Validation="@this.providerValidation.ValidatingInstanceName" UserAttributes="@SPELLCHECK_ATTRIBUTES" /> diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs index 55693522..9e5fcb6e 100644 --- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs @@ -1,5 +1,6 @@ using AIStudio.Provider; using AIStudio.Settings; +using AIStudio.Tools.Validation; using Microsoft.AspNetCore.Components; @@ -98,6 +99,19 @@ public partial class ProviderDialog : ComponentBase, ISecretId private readonly List availableModels = new(); private readonly Encryption encryption = Program.ENCRYPTION; + private readonly ProviderValidation providerValidation; + + public ProviderDialog() + { + this.providerValidation = new() + { + GetProvider = () => this.DataLLMProvider, + GetAPIKeyStorageIssue = () => this.dataAPIKeyStorageIssue, + GetPreviousInstanceName = () => this.dataEditingPreviousInstanceName, + GetUsedInstanceNames = () => this.UsedInstanceNames, + GetHost = () => this.DataHost, + }; + } private Settings.Provider CreateProviderSettings() { @@ -212,25 +226,6 @@ public partial class ProviderDialog : ComponentBase, ISecretId this.MudDialog.Close(DialogResult.Ok(addedProviderSettings)); } - private string? ValidatingProvider(LLMProviders llmProvider) - { - if (llmProvider == LLMProviders.NONE) - return "Please select a provider."; - - return null; - } - - private string? ValidatingHost(Host host) - { - if(this.DataLLMProvider is not LLMProviders.SELF_HOSTED) - return null; - - if (host == Host.NONE) - return "Please select a host."; - - return null; - } - private string? ValidateManuallyModel(string manuallyModel) { if (this.DataLLMProvider is LLMProviders.FIREWORKS && string.IsNullOrWhiteSpace(manuallyModel)) @@ -238,64 +233,6 @@ public partial class ProviderDialog : ComponentBase, ISecretId return null; } - - private string? ValidatingModel(Model model) - { - if(this.DataLLMProvider is LLMProviders.SELF_HOSTED && this.DataHost == Host.LLAMACPP) - return null; - - if (model == default) - return "Please select a model."; - - return null; - } - - private string? ValidatingInstanceName(string instanceName) - { - if (string.IsNullOrWhiteSpace(instanceName)) - return "Please enter an instance name."; - - if (instanceName.Length > 40) - return "The instance name must not exceed 40 characters."; - - // The instance name must be unique: - var lowerInstanceName = instanceName.ToLowerInvariant(); - if (lowerInstanceName != this.dataEditingPreviousInstanceName && this.UsedInstanceNames.Contains(lowerInstanceName)) - return "The instance name must be unique; the chosen name is already in use."; - - return null; - } - - private string? ValidatingAPIKey(string apiKey) - { - if(this.DataLLMProvider is LLMProviders.SELF_HOSTED) - return null; - - if(!string.IsNullOrWhiteSpace(this.dataAPIKeyStorageIssue)) - return this.dataAPIKeyStorageIssue; - - if(string.IsNullOrWhiteSpace(apiKey)) - return "Please enter an API key."; - - return null; - } - - private string? ValidatingHostname(string hostname) - { - if(this.DataLLMProvider != LLMProviders.SELF_HOSTED) - return null; - - if(string.IsNullOrWhiteSpace(hostname)) - return "Please enter a hostname, e.g., http://localhost:1234"; - - if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) - return "The hostname must start with either http:// or https://"; - - if(!Uri.TryCreate(hostname, UriKind.Absolute, out _)) - return "The hostname is not a valid HTTP(S) URL."; - - return null; - } private void Cancel() => this.MudDialog.Cancel(); diff --git a/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs b/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs new file mode 100644 index 00000000..be7b16be --- /dev/null +++ b/app/MindWork AI Studio/Tools/Validation/ProviderValidation.cs @@ -0,0 +1,96 @@ +using AIStudio.Provider; + +using Host = AIStudio.Provider.SelfHosted.Host; + +namespace AIStudio.Tools.Validation; + +public sealed class ProviderValidation +{ + public Func GetProvider { get; init; } = () => LLMProviders.NONE; + + public Func GetAPIKeyStorageIssue { get; init; } = () => string.Empty; + + public Func GetPreviousInstanceName { get; init; } = () => string.Empty; + + public Func> GetUsedInstanceNames { get; init; } = () => []; + + public Func GetHost { get; init; } = () => Host.NONE; + + public string? ValidatingHostname(string hostname) + { + if(this.GetProvider() != LLMProviders.SELF_HOSTED) + return null; + + if(string.IsNullOrWhiteSpace(hostname)) + return "Please enter a hostname, e.g., http://localhost:1234"; + + if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) + return "The hostname must start with either http:// or https://"; + + if(!Uri.TryCreate(hostname, UriKind.Absolute, out _)) + return "The hostname is not a valid HTTP(S) URL."; + + return null; + } + + public string? ValidatingAPIKey(string apiKey) + { + if(this.GetProvider() is LLMProviders.SELF_HOSTED) + return null; + + var apiKeyStorageIssue = this.GetAPIKeyStorageIssue(); + if(!string.IsNullOrWhiteSpace(apiKeyStorageIssue)) + return apiKeyStorageIssue; + + if(string.IsNullOrWhiteSpace(apiKey)) + return "Please enter an API key."; + + return null; + } + + public string? ValidatingInstanceName(string instanceName) + { + if (string.IsNullOrWhiteSpace(instanceName)) + return "Please enter an instance name."; + + if (instanceName.Length > 40) + return "The instance name must not exceed 40 characters."; + + // The instance name must be unique: + var lowerInstanceName = instanceName.ToLowerInvariant(); + if (lowerInstanceName != this.GetPreviousInstanceName() && this.GetUsedInstanceNames().Contains(lowerInstanceName)) + return "The instance name must be unique; the chosen name is already in use."; + + return null; + } + + public string? ValidatingModel(Model model) + { + if(this.GetProvider() is LLMProviders.SELF_HOSTED && this.GetHost() == Host.LLAMACPP) + return null; + + if (model == default) + return "Please select a model."; + + return null; + } + + public string? ValidatingProvider(LLMProviders llmProvider) + { + if (llmProvider == LLMProviders.NONE) + return "Please select a provider."; + + return null; + } + + public string? ValidatingHost(Host host) + { + if(this.GetProvider() is not LLMProviders.SELF_HOSTED) + return null; + + if (host == Host.NONE) + return "Please select a host."; + + return null; + } +} \ No newline at end of file