diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpointUrls.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpointUrls.cs
index b8ccbd2b..13faee0e 100644
--- a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpointUrls.cs
+++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpointUrls.cs
@@ -12,4 +12,12 @@ public static class PlaygroundEndpointUrls
/// - GET method for listing all events
///
public const string Events = "/events";
+
+ ///
+ /// Declares the deployment models list endpoint.
+ ///
+ ///
+ /// - GET method for listing all deployment models
+ ///
+ public const string DeploymentModels = "/events/{eventId}/deployment-models";
}
diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs
index c21d6029..91c01b8f 100644
--- a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs
+++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs
@@ -1,3 +1,5 @@
+using Microsoft.AspNetCore.Mvc;
+
namespace AzureOpenAIProxy.ApiApp.Endpoints;
///
@@ -32,4 +34,36 @@ public static RouteHandlerBuilder AddListEvents(this WebApplication app)
return builder;
}
+
+
+ ///
+ /// Adds the get deployment models
+ ///
+ /// instance.
+ /// Returns instance.
+ public static RouteHandlerBuilder AddListDeploymentModels(this WebApplication app)
+ {
+ // Todo: Issue #170 https://github.com/aliencube/azure-openai-sdk-proxy/issues/170
+ var builder = app.MapGet(PlaygroundEndpointUrls.DeploymentModels, (
+ [FromRoute] string eventId
+ ) =>
+ {
+ return Results.Ok();
+ })
+ .Produces>(statusCode: StatusCodes.Status200OK, contentType: "application/json")
+ .Produces(statusCode: StatusCodes.Status401Unauthorized)
+ .Produces(statusCode: StatusCodes.Status404NotFound)
+ .Produces(statusCode: StatusCodes.Status500InternalServerError, contentType: "text/plain")
+ .WithTags("events")
+ .WithName("GetDeploymentModels")
+ .WithOpenApi(operation =>
+ {
+ operation.Summary = "Gets all deployment models";
+ operation.Description = "This endpoint gets all deployment models avaliable";
+
+ return operation;
+ });
+
+ return builder;
+ }
}
\ No newline at end of file
diff --git a/src/AzureOpenAIProxy.ApiApp/Models/DeploymentModelDetails.cs b/src/AzureOpenAIProxy.ApiApp/Models/DeploymentModelDetails.cs
new file mode 100644
index 00000000..ab2ef317
--- /dev/null
+++ b/src/AzureOpenAIProxy.ApiApp/Models/DeploymentModelDetails.cs
@@ -0,0 +1,14 @@
+using System.Text.Json.Serialization;
+
+///
+/// This represent the event detail data for response by admin event endpoint.
+///
+public class DeploymentModelDetails
+{
+ ///
+ /// Gets or sets the deployment model name.
+ ///
+ [JsonRequired]
+ public string Name { get; set; } = string.Empty;
+
+}
\ No newline at end of file
diff --git a/src/AzureOpenAIProxy.ApiApp/Program.cs b/src/AzureOpenAIProxy.ApiApp/Program.cs
index 17d22e2e..f35b83ee 100644
--- a/src/AzureOpenAIProxy.ApiApp/Program.cs
+++ b/src/AzureOpenAIProxy.ApiApp/Program.cs
@@ -57,6 +57,7 @@
// Playground endpoints
app.AddListEvents();
+app.AddListDeploymentModels();
// Admin endpoints
app.AddNewAdminEvent();
diff --git a/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/GetDeploymentModelsOpenApiTest.cs b/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/GetDeploymentModelsOpenApiTest.cs
new file mode 100644
index 00000000..51e72085
--- /dev/null
+++ b/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/GetDeploymentModelsOpenApiTest.cs
@@ -0,0 +1,230 @@
+using System.Text.Json;
+
+using AzureOpenAIProxy.AppHost.Tests.Fixtures;
+
+using FluentAssertions;
+
+using IdentityModel.Client;
+
+
+namespace AzureOpenAIProxy.AppHost.Tests.ApiApp.Endpoints;
+
+public class GetDeploymentModelsOpenApiTests(AspireAppHostFixture host) : IClassFixture
+{
+ [Fact]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Path()
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .TryGetProperty("/events/{eventId}/deployment-models", out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+ [Fact]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Verb()
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .TryGetProperty("get", out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+ [Theory]
+ [InlineData("events")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Tags(string tag)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .GetProperty("get")
+ .TryGetProperty("tags", out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Array);
+ result.EnumerateArray().Select(p => p.GetString()).Should().Contain(tag);
+ }
+
+ [Theory]
+ [InlineData("summary")]
+ [InlineData("description")]
+ [InlineData("operationId")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Value(string attribute)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .GetProperty("get")
+ .TryGetProperty(attribute, out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.String);
+ }
+
+
+ [Theory]
+ [InlineData("eventId")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Path_Parameter(string name)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var openapi = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = openapi!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .GetProperty("get")
+ .GetProperty("parameters")
+ .EnumerateArray()
+ .Where(p => p.GetProperty("in").GetString() == "path")
+ .Select(p => p.GetProperty("name").ToString());
+ result.Should().Contain(name);
+ }
+
+ [Theory]
+ [InlineData("responses")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Object(string attribute)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .GetProperty("get")
+ .TryGetProperty(attribute, out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+ [Theory]
+ [InlineData("200")]
+ [InlineData("401")]
+ [InlineData("404")]
+ [InlineData("500")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Response(string attribute)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var apiDocument = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = apiDocument!.RootElement.GetProperty("paths")
+ .GetProperty("/events/{eventId}/deployment-models")
+ .GetProperty("get")
+ .GetProperty("responses")
+ .TryGetProperty(attribute, out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+
+ [Fact]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Model()
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var openapi = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = openapi!.RootElement.GetProperty("components")
+ .GetProperty("schemas")
+ .TryGetProperty("DeploymentModelDetails", out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+ [Theory]
+ [InlineData("name", true)]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Required(string attribute, bool isRequired)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var openapi = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = openapi!.RootElement.GetProperty("components")
+ .GetProperty("schemas")
+ .GetProperty("DeploymentModelDetails")
+ .TryGetStringArray("required")
+ .ToList();
+ result.Contains(attribute).Should().Be(isRequired);
+ }
+
+ [Theory]
+ [InlineData("name")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Property(string attribute)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var openapi = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = openapi!.RootElement.GetProperty("components")
+ .GetProperty("schemas")
+ .GetProperty("DeploymentModelDetails")
+ .GetProperty("properties")
+ .TryGetProperty(attribute, out var property) ? property : default;
+ result.ValueKind.Should().Be(JsonValueKind.Object);
+ }
+
+ [Theory]
+ [InlineData("name", "string")]
+ public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Type(string attribute, string type)
+ {
+ // Arrange
+ using var httpClient = host.App!.CreateHttpClient("apiapp");
+
+ // Act
+ var json = await httpClient.GetStringAsync("/swagger/v1.0.0/swagger.json");
+ var openapi = JsonSerializer.Deserialize(json);
+
+ // Assert
+ var result = openapi!.RootElement.GetProperty("components")
+ .GetProperty("schemas")
+ .GetProperty("DeploymentModelDetails")
+ .GetProperty("properties")
+ .GetProperty(attribute);
+ result.TryGetString("type").Should().Be(type);
+ }
+}
\ No newline at end of file