|
1 | 1 | using Microsoft.Extensions.AI; |
2 | 2 | using Microsoft.Extensions.Configuration; |
3 | 3 | using Microsoft.Extensions.DependencyInjection; |
| 4 | +using OpenAI; |
| 5 | +using xAI; |
4 | 6 |
|
5 | 7 | namespace Devlooped.Extensions.AI; |
6 | 8 |
|
@@ -32,6 +34,37 @@ public void CanConfigureClients() |
32 | 34 | Assert.Equal("xai", grok.GetRequiredService<ChatClientMetadata>().ProviderName); |
33 | 35 | } |
34 | 36 |
|
| 37 | + [Fact] |
| 38 | + public void CanGetClientOptions() |
| 39 | + { |
| 40 | + var configuration = new ConfigurationBuilder() |
| 41 | + .AddInMemoryCollection(new Dictionary<string, string?> |
| 42 | + { |
| 43 | + ["ai:clients:openai:modelid"] = "gpt-4.1.nano", |
| 44 | + ["ai:clients:openai:ApiKey"] = "sk-asdfasdf", |
| 45 | + ["ai:clients:grok:modelid"] = "grok-4-fast", |
| 46 | + ["ai:clients:grok:ApiKey"] = "xai-asdfasdf", |
| 47 | + ["ai:clients:grok:endpoint"] = "https://api.x.ai", |
| 48 | + }) |
| 49 | + .Build(); |
| 50 | + |
| 51 | + var services = new ServiceCollection() |
| 52 | + .AddSingleton<IConfiguration>(configuration) |
| 53 | + .AddChatClients(configuration) |
| 54 | + .BuildServiceProvider(); |
| 55 | + |
| 56 | + var openai = services.GetRequiredKeyedService<IChatClient>("openai"); |
| 57 | + var grok = services.GetRequiredKeyedService<IChatClient>("grok"); |
| 58 | + |
| 59 | + // Untyped by name+object |
| 60 | + Assert.NotNull(openai.GetService<object>("options")); |
| 61 | + // Typed to concrete options, no need for key |
| 62 | + Assert.NotNull(openai.GetService<OpenAIClientOptions>()); |
| 63 | + |
| 64 | + Assert.NotNull(grok.GetService<object>("Options")); |
| 65 | + Assert.NotNull(grok.GetService<GrokClientOptions>()); |
| 66 | + } |
| 67 | + |
35 | 68 | [Fact] |
36 | 69 | public void CanGetFromAlternativeKey() |
37 | 70 | { |
@@ -259,4 +292,108 @@ public void CanConfigureAzureOpenAI() |
259 | 292 | Assert.Equal("azure.ai.openai", client.GetRequiredService<ChatClientMetadata>().ProviderName); |
260 | 293 | Assert.Equal("gpt-5", client.GetRequiredService<ChatClientMetadata>().DefaultModelId); |
261 | 294 | } |
| 295 | + |
| 296 | + [Fact] |
| 297 | + public void CanInspectOpenAIProviderOptions() |
| 298 | + { |
| 299 | + var configuration = new ConfigurationBuilder() |
| 300 | + .AddInMemoryCollection(new Dictionary<string, string?> |
| 301 | + { |
| 302 | + ["ai:clients:openai:modelid"] = "gpt-4.1.nano", |
| 303 | + ["ai:clients:openai:apikey"] = "sk-asdfasdf", |
| 304 | + ["ai:clients:openai:UserAgentApplicationId"] = "myapp/1.0", |
| 305 | + }) |
| 306 | + .Build(); |
| 307 | + |
| 308 | + var services = new ServiceCollection() |
| 309 | + .AddSingleton<IConfiguration>(configuration) |
| 310 | + .AddChatClients(configuration) |
| 311 | + .BuildServiceProvider(); |
| 312 | + |
| 313 | + var client = services.GetRequiredKeyedService<IChatClient>("openai"); |
| 314 | + var options = Assert.IsType<OpenAIChatClientProvider.OpenAIProviderOptions>( |
| 315 | + client.GetService(typeof(object), "OpTiOnS")); |
| 316 | + |
| 317 | + Assert.Same(options, client.GetService(typeof(OpenAIChatClientProvider.OpenAIProviderOptions), "options")); |
| 318 | + Assert.Equal("gpt-4.1.nano", options.ModelId); |
| 319 | + Assert.Equal("myapp/1.0", options.UserAgentApplicationId); |
| 320 | + } |
| 321 | + |
| 322 | + [Fact] |
| 323 | + public void CanInspectAzureOpenAIProviderOptions() |
| 324 | + { |
| 325 | + var configuration = new ConfigurationBuilder() |
| 326 | + .AddInMemoryCollection(new Dictionary<string, string?> |
| 327 | + { |
| 328 | + ["ai:clients:chat:modelid"] = "gpt-5", |
| 329 | + ["ai:clients:chat:apikey"] = "asdfasdf", |
| 330 | + ["ai:clients:chat:endpoint"] = "https://chat.openai.azure.com/", |
| 331 | + ["ai:clients:chat:UserAgentApplicationId"] = "myapp/1.0", |
| 332 | + }) |
| 333 | + .Build(); |
| 334 | + |
| 335 | + var services = new ServiceCollection() |
| 336 | + .AddSingleton<IConfiguration>(configuration) |
| 337 | + .AddChatClients(configuration) |
| 338 | + .BuildServiceProvider(); |
| 339 | + |
| 340 | + var client = services.GetRequiredKeyedService<IChatClient>("chat"); |
| 341 | + var options = Assert.IsType<AzureOpenAIChatClientProvider.AzureOpenAIProviderOptions>( |
| 342 | + client.GetService(typeof(object), "options")); |
| 343 | + |
| 344 | + Assert.Same(options, client.GetService(typeof(AzureOpenAIChatClientProvider.AzureOpenAIProviderOptions), "OPTIONS")); |
| 345 | + Assert.Equal(new Uri("https://chat.openai.azure.com/"), options.Endpoint); |
| 346 | + Assert.Equal("myapp/1.0", options.UserAgentApplicationId); |
| 347 | + } |
| 348 | + |
| 349 | + [Fact] |
| 350 | + public void CanInspectAzureInferenceProviderOptions() |
| 351 | + { |
| 352 | + var configuration = new ConfigurationBuilder() |
| 353 | + .AddInMemoryCollection(new Dictionary<string, string?> |
| 354 | + { |
| 355 | + ["ai:clients:chat:modelid"] = "gpt-5", |
| 356 | + ["ai:clients:chat:apikey"] = "asdfasdf", |
| 357 | + ["ai:clients:chat:endpoint"] = "https://ai.azure.com/.default", |
| 358 | + }) |
| 359 | + .Build(); |
| 360 | + |
| 361 | + var services = new ServiceCollection() |
| 362 | + .AddSingleton<IConfiguration>(configuration) |
| 363 | + .AddChatClients(configuration) |
| 364 | + .BuildServiceProvider(); |
| 365 | + |
| 366 | + var client = services.GetRequiredKeyedService<IChatClient>("chat"); |
| 367 | + var options = Assert.IsType<AzureAIInferenceChatClientProvider.AzureInferenceProviderOptions>( |
| 368 | + client.GetService(typeof(object), "options")); |
| 369 | + |
| 370 | + Assert.Same(options, client.GetService(typeof(AzureAIInferenceChatClientProvider.AzureInferenceProviderOptions), "OPTIONS")); |
| 371 | + Assert.Equal(new Uri("https://ai.azure.com/.default"), options.Endpoint); |
| 372 | + Assert.Equal("gpt-5", options.ModelId); |
| 373 | + } |
| 374 | + |
| 375 | + [Fact] |
| 376 | + public void CanInspectGrokProviderOptions() |
| 377 | + { |
| 378 | + var configuration = new ConfigurationBuilder() |
| 379 | + .AddInMemoryCollection(new Dictionary<string, string?> |
| 380 | + { |
| 381 | + ["ai:clients:grok:modelid"] = "grok-4-fast", |
| 382 | + ["ai:clients:grok:apikey"] = "xai-asdfasdf", |
| 383 | + ["ai:clients:grok:endpoint"] = "https://api.x.ai", |
| 384 | + }) |
| 385 | + .Build(); |
| 386 | + |
| 387 | + var services = new ServiceCollection() |
| 388 | + .AddSingleton<IConfiguration>(configuration) |
| 389 | + .AddChatClients(configuration) |
| 390 | + .BuildServiceProvider(); |
| 391 | + |
| 392 | + var client = services.GetRequiredKeyedService<IChatClient>("grok"); |
| 393 | + var options = Assert.IsType<GrokChatClientProvider.GrokProviderOptions>( |
| 394 | + client.GetService(typeof(object), "options")); |
| 395 | + |
| 396 | + Assert.Same(options, client.GetService(typeof(GrokChatClientProvider.GrokProviderOptions), "OPTIONS")); |
| 397 | + Assert.Equal("grok-4-fast", options.ModelId); |
| 398 | + } |
262 | 399 | } |
0 commit comments