diff --git a/app/MindWork AI Studio/Provider/IProvider.cs b/app/MindWork AI Studio/Provider/IProvider.cs index 153ebba..776d981 100644 --- a/app/MindWork AI Studio/Provider/IProvider.cs +++ b/app/MindWork AI Studio/Provider/IProvider.cs @@ -48,16 +48,18 @@ public interface IProvider /// /// The JS runtime to access the Rust code. /// The settings manager to access the API key. + /// The provisional API key to use. Useful when the user is adding a new provider. When null, the stored API key is used. /// The cancellation token. /// The list of text models. - public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default); - + public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default); + /// /// Load all possible image models that can be used with this provider. /// /// The JS runtime to access the Rust code. /// The settings manager to access the API key. + /// The provisional API key to use. Useful when the user is adding a new provider. When null, the stored API key is used. /// The cancellation token. /// The list of image models. - public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default); + public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/NoProvider.cs b/app/MindWork AI Studio/Provider/NoProvider.cs index 5c0a9e5..b5b9b2f 100644 --- a/app/MindWork AI Studio/Provider/NoProvider.cs +++ b/app/MindWork AI Studio/Provider/NoProvider.cs @@ -13,9 +13,9 @@ public class NoProvider : IProvider public string InstanceName { get; set; } = "None"; - public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default) => Task.FromResult>([]); + public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default) => Task.FromResult>([]); - public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default) => Task.FromResult>([]); + public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default) => Task.FromResult>([]); public async IAsyncEnumerable StreamChatCompletion(IJSRuntime jsRuntime, SettingsManager settings, Model chatModel, ChatThread chatChatThread, [EnumeratorCancellation] CancellationToken token = default) { diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index f883a6e..33865b3 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -151,27 +151,36 @@ public sealed class ProviderOpenAI() : BaseProvider("https://api.openai.com/v1/" #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default) + public Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default) { - return this.LoadModels(jsRuntime, settings, "gpt-", token); + return this.LoadModels(jsRuntime, settings, "gpt-", token, apiKeyProvisional); } /// - public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, CancellationToken token = default) + public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default) { - return this.LoadModels(jsRuntime, settings, "dall-e-", token); + return this.LoadModels(jsRuntime, settings, "dall-e-", token, apiKeyProvisional); } #endregion - private async Task> LoadModels(IJSRuntime jsRuntime, SettingsManager settings, string prefix, CancellationToken token) + private async Task> LoadModels(IJSRuntime jsRuntime, SettingsManager settings, string prefix, CancellationToken token, string? apiKeyProvisional = null) { - var requestedSecret = await settings.GetAPIKey(jsRuntime, this); - if (!requestedSecret.Success) + var secretKey = apiKeyProvisional switch + { + not null => apiKeyProvisional, + _ => await settings.GetAPIKey(jsRuntime, this) switch + { + { Success: true } result => result.Secret, + _ => null, + } + }; + + if (secretKey is null) return []; var request = new HttpRequestMessage(HttpMethod.Get, "models"); - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", requestedSecret.Secret); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", secretKey); var response = await this.httpClient.SendAsync(request, token); if(!response.IsSuccessStatusCode)