From 81107aa0942865bea02219b01d7097c9d6062e4d Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Mon, 28 Jul 2025 09:59:18 -0700 Subject: [PATCH 1/2] Add constructor with AuthenticationPolicy to ChatClient --- api/OpenAI.net8.0.cs | 2 ++ api/OpenAI.netstandard2.0.cs | 2 ++ src/Custom/Chat/ChatClient.cs | 27 ++++++++++++++++++++++++--- src/Custom/OpenAIClient.cs | 26 +++++++++++++++++--------- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/api/OpenAI.net8.0.cs b/api/OpenAI.net8.0.cs index 57bff3c5d..7cdb42184 100644 --- a/api/OpenAI.net8.0.cs +++ b/api/OpenAI.net8.0.cs @@ -1402,6 +1402,8 @@ public class ChatClient { protected internal ChatClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential); + public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options); + public ChatClient(string model, AuthenticationPolicy authenticationPolicy); public ChatClient(string model, string apiKey); public ClientPipeline Pipeline { get; } public virtual ClientResult CompleteChat(params ChatMessage[] messages); diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs index 10c9b626b..aa98475ae 100644 --- a/api/OpenAI.netstandard2.0.cs +++ b/api/OpenAI.netstandard2.0.cs @@ -1265,6 +1265,8 @@ public class ChatClient { protected internal ChatClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential); + public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options); + public ChatClient(string model, AuthenticationPolicy authenticationPolicy); public ChatClient(string model, string apiKey); public ClientPipeline Pipeline { get; } public virtual ClientResult CompleteChat(params ChatMessage[] messages); diff --git a/src/Custom/Chat/ChatClient.cs b/src/Custom/Chat/ChatClient.cs index f88d4bfe8..90a5a5e46 100644 --- a/src/Custom/Chat/ChatClient.cs +++ b/src/Custom/Chat/ChatClient.cs @@ -66,14 +66,35 @@ public partial class ChatClient /// The options to configure the client. /// or is null. /// is an empty string, and was expected to be non-empty. - public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) + public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) : this(model, OpenAIClient.CreateApiKeyAuthenticationPolicy(credential), options) + { + } + + // CUSTOM: Added as a convenience. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The authentication policy used to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ChatClient(string model, AuthenticationPolicy authenticationPolicy) : this(model, authenticationPolicy, new OpenAIClientOptions()) + { + } + + // CUSTOM: Added as a convenience. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The authentication policy used to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options) { Argument.AssertNotNullOrEmpty(model, nameof(model)); - Argument.AssertNotNull(credential, nameof(credential)); + Argument.AssertNotNull(authenticationPolicy, nameof(authenticationPolicy)); options ??= new OpenAIClientOptions(); _model = model; - Pipeline = OpenAIClient.CreatePipeline(credential, options); + Pipeline = OpenAIClient.CreatePipeline(authenticationPolicy, options); _endpoint = OpenAIClient.GetEndpoint(options); _telemetry = new OpenTelemetrySource(model, _endpoint); } diff --git a/src/Custom/OpenAIClient.cs b/src/Custom/OpenAIClient.cs index b3b724c9e..bc32662f1 100644 --- a/src/Custom/OpenAIClient.cs +++ b/src/Custom/OpenAIClient.cs @@ -316,18 +316,26 @@ protected internal OpenAIClient(ClientPipeline pipeline, OpenAIClientOptions opt [Experimental("OPENAI001")] public virtual ContainerClient GetContainerClient() => new(Pipeline, _options); + internal static AuthenticationPolicy CreateApiKeyAuthenticationPolicy(ApiKeyCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + return ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy(credential, AuthorizationHeader, AuthorizationApiKeyPrefix); + } + internal static ClientPipeline CreatePipeline(ApiKeyCredential credential, OpenAIClientOptions options) + { + return CreatePipeline( + authenticationPolicy: ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy(credential, AuthorizationHeader, AuthorizationApiKeyPrefix), + options); + } + + internal static ClientPipeline CreatePipeline(AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options) { return ClientPipeline.Create( - options, - perCallPolicies: [ - CreateAddCustomHeadersPolicy(options), - ], - perTryPolicies: [ - ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy(credential, AuthorizationHeader, AuthorizationApiKeyPrefix) - ], - beforeTransportPolicies: [ - ]); + options: options, + perCallPolicies: [CreateAddCustomHeadersPolicy(options)], + perTryPolicies: [authenticationPolicy], + beforeTransportPolicies: []); } internal static Uri GetEndpoint(OpenAIClientOptions options = null) From 2e0e08ce1a1c39e4172daf39c2bf2abbe4823107 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 29 Jul 2025 17:29:17 -0700 Subject: [PATCH 2/2] Add Experimental attribute --- api/OpenAI.net8.0.cs | 2 ++ src/Custom/Chat/ChatClient.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/api/OpenAI.net8.0.cs b/api/OpenAI.net8.0.cs index 7cdb42184..35759f89d 100644 --- a/api/OpenAI.net8.0.cs +++ b/api/OpenAI.net8.0.cs @@ -1402,7 +1402,9 @@ public class ChatClient { protected internal ChatClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); public ChatClient(string model, ApiKeyCredential credential); + [Experimental("OPENAI001")] public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options); + [Experimental("OPENAI001")] public ChatClient(string model, AuthenticationPolicy authenticationPolicy); public ChatClient(string model, string apiKey); public ClientPipeline Pipeline { get; } diff --git a/src/Custom/Chat/ChatClient.cs b/src/Custom/Chat/ChatClient.cs index 90a5a5e46..74cf5624b 100644 --- a/src/Custom/Chat/ChatClient.cs +++ b/src/Custom/Chat/ChatClient.cs @@ -76,6 +76,7 @@ public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions /// The authentication policy used to authenticate with the service. /// or is null. /// is an empty string, and was expected to be non-empty. + [Experimental("OPENAI001")] public ChatClient(string model, AuthenticationPolicy authenticationPolicy) : this(model, authenticationPolicy, new OpenAIClientOptions()) { } @@ -87,6 +88,7 @@ public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions /// The options to configure the client. /// or is null. /// is an empty string, and was expected to be non-empty. + [Experimental("OPENAI001")] public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options) { Argument.AssertNotNullOrEmpty(model, nameof(model));