1- using System . ClientModel . Primitives ;
1+ using System ;
2+ using System . ClientModel . Primitives ;
23using System . ComponentModel ;
34using Azure ;
45using Azure . AI . Inference ;
@@ -25,6 +26,7 @@ public sealed partial class ConfigurableChatClient : IChatClient, IDisposable
2526 readonly Action < string , IChatClient > ? configure ;
2627 IDisposable reloadToken ;
2728 IChatClient innerClient ;
29+ ChatClientMetadata metadata ;
2830 object ? options ;
2931
3032 /// <summary>
@@ -46,28 +48,33 @@ public ConfigurableChatClient(IConfiguration configuration, ILogger logger, stri
4648 this . id = Throw . IfNullOrEmpty ( id ) ;
4749 this . configure = configure ;
4850
49- innerClient = Configure ( configuration . GetRequiredSection ( section ) ) ;
51+ ( innerClient , metadata ) = Configure ( configuration . GetRequiredSection ( section ) ) ;
5052 reloadToken = configuration . GetReloadToken ( ) . RegisterChangeCallback ( OnReload , state : null ) ;
5153 }
5254
5355 /// <summary>Disposes the client and stops monitoring configuration changes.</summary>
5456 public void Dispose ( ) => reloadToken ? . Dispose ( ) ;
5557
58+ /// <inheritdoc/>
59+ public object ? GetService ( Type serviceType , object ? serviceKey = null ) => serviceType switch
60+ {
61+ Type t when typeof ( ChatClientMetadata ) . IsAssignableFrom ( t ) => metadata ,
62+ Type t when t == typeof ( IChatClient ) => this ,
63+ _ => innerClient . GetService ( serviceType , serviceKey )
64+ } ;
65+
5666 /// <inheritdoc/>
5767 public Task < ChatResponse > GetResponseAsync ( IEnumerable < ChatMessage > messages , ChatOptions ? options = null , CancellationToken cancellationToken = default )
5868 => innerClient . GetResponseAsync ( messages , options , cancellationToken ) ;
5969 /// <inheritdoc/>
6070 public IAsyncEnumerable < ChatResponseUpdate > GetStreamingResponseAsync ( IEnumerable < ChatMessage > messages , ChatOptions ? options = null , CancellationToken cancellationToken = default )
6171 => innerClient . GetStreamingResponseAsync ( messages , options , cancellationToken ) ;
62- /// <inheritdoc/>
63- public object ? GetService ( Type serviceType , object ? serviceKey = null )
64- => innerClient . GetService ( serviceType , serviceKey ) ;
6572
6673 /// <summary>Exposes the optional <see cref="ClientPipelineOptions"/> configured for the client.</summary>
6774 [ EditorBrowsable ( EditorBrowsableState . Never ) ]
6875 public object ? Options => options ;
6976
70- IChatClient Configure ( IConfigurationSection configSection )
77+ ( IChatClient , ChatClientMetadata ) Configure ( IConfigurationSection configSection )
7178 {
7279 var options = SetOptions < ConfigurableClientOptions > ( configSection ) ;
7380 Throw . IfNullOrEmpty ( options ? . ModelId , $ "{ configSection } :modelid") ;
@@ -107,7 +114,9 @@ IChatClient Configure(IConfigurationSection configSection)
107114
108115 LogConfigured ( id ) ;
109116
110- return client ;
117+ var metadata = client . GetService < ChatClientMetadata > ( ) ?? new ChatClientMetadata ( null , null , null ) ;
118+
119+ return ( client , new ConfigurableChatClientMetadata ( id , section , metadata . ProviderName , metadata . ProviderUri , metadata . DefaultModelId ) ) ;
111120 }
112121
113122 TOptions ? SetOptions < TOptions > ( IConfigurationSection section ) where TOptions : class
@@ -133,7 +142,7 @@ void OnReload(object? state)
133142 ( innerClient as IDisposable ) ? . Dispose ( ) ;
134143 reloadToken ? . Dispose ( ) ;
135144
136- innerClient = Configure ( configSection ) ;
145+ ( innerClient , metadata ) = Configure ( configSection ) ;
137146
138147 reloadToken = configuration . GetReloadToken ( ) . RegisterChangeCallback ( OnReload , state : null ) ;
139148 }
@@ -158,4 +167,14 @@ internal class ConfigurableAzureOptions : AzureOpenAIClientOptions
158167 public string ? ApiKey { get ; set ; }
159168 public string ? ModelId { get ; set ; }
160169 }
170+ }
171+
172+ /// <summary>Metadata for a <see cref="ConfigurableChatClient"/>.</summary>
173+ public class ConfigurableChatClientMetadata ( string id , string configurationSection , string ? providerName , Uri ? providerUri , string ? defaultModelId )
174+ : ChatClientMetadata ( providerName , providerUri , defaultModelId )
175+ {
176+ /// <summary>The unique identifier of the configurable client.</summary>
177+ public string Id => id ;
178+ /// <summary>The configuration section used to configure the client.</summary>
179+ public string ConfigurationSection => configurationSection ;
161180}
0 commit comments