feat: implement CreateMessageBatchAsync method
This commit is contained in:
@@ -28,6 +28,13 @@ public interface IAnthropicApiClient
|
|||||||
/// <returns>An asynchronous enumerable that yields the response event by event.</returns>
|
/// <returns>An asynchronous enumerable that yields the response event by event.</returns>
|
||||||
IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request);
|
IAsyncEnumerable<AnthropicEvent> CreateMessageAsync(StreamMessageRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a batch of messages asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The message batch request to create.</param>
|
||||||
|
/// <returns>A task that represents the asynchronous operation. The task result contains the response as an <see cref="AnthropicResult{T}"/> where T is <see cref="MessageBatchResponse"/>.</returns>
|
||||||
|
Task<AnthropicResult<MessageBatchResponse>> CreateMessageBatchAsync(MessageBatchRequest request);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Counts the tokens in a message asynchronously.
|
/// Counts the tokens in a message asynchronously.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -64,7 +71,8 @@ public class AnthropicApiClient : IAnthropicApiClient
|
|||||||
private const string BaseUrl = "https://api.anthropic.com/v1/";
|
private const string BaseUrl = "https://api.anthropic.com/v1/";
|
||||||
private const string ApiKeyHeader = "x-api-key";
|
private const string ApiKeyHeader = "x-api-key";
|
||||||
private const string MessagesEndpoint = "messages";
|
private const string MessagesEndpoint = "messages";
|
||||||
private const string CountTokensEndpoint = "messages/count_tokens";
|
private string CountTokensEndpoint => $"{MessagesEndpoint}/count-tokens";
|
||||||
|
private string MessageBatchesEndpoint => $"{MessagesEndpoint}/batches";
|
||||||
private const string ModelsEndpoint = "models";
|
private const string ModelsEndpoint = "models";
|
||||||
private const string JsonContentType = "application/json";
|
private const string JsonContentType = "application/json";
|
||||||
private const string EventPrefix = "event:";
|
private const string EventPrefix = "event:";
|
||||||
@@ -287,6 +295,23 @@ public class AnthropicApiClient : IAnthropicApiClient
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<AnthropicResult<MessageBatchResponse>> CreateMessageBatchAsync(MessageBatchRequest request)
|
||||||
|
{
|
||||||
|
var response = await SendRequestAsync(MessageBatchesEndpoint, request);
|
||||||
|
var anthropicHeaders = new AnthropicHeaders(response.Headers);
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode is false)
|
||||||
|
{
|
||||||
|
var error = Deserialize<AnthropicError>(responseContent) ?? new AnthropicError();
|
||||||
|
return AnthropicResult<MessageBatchResponse>.Failure(error, anthropicHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgBatchResponse = Deserialize<MessageBatchResponse>(responseContent) ?? new MessageBatchResponse();
|
||||||
|
return AnthropicResult<MessageBatchResponse>.Success(msgBatchResponse, anthropicHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task<AnthropicResult<TokenCountResponse>> CountMessageTokensAsync(CountMessageTokensRequest request)
|
public async Task<AnthropicResult<TokenCountResponse>> CountMessageTokensAsync(CountMessageTokensRequest request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace AnthropicClient.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request to create a batch of messages.
|
||||||
|
/// </summary>
|
||||||
|
public class MessageBatchRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the requests to create messages.
|
||||||
|
/// </summary>
|
||||||
|
public List<MessageBatchRequestItem> Requests { get; init; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MessageBatchRequest"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requests">The requests to create messages.</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown when <paramref name="requests"/> is empty.</exception>
|
||||||
|
/// <returns>An instance of the <see cref="MessageBatchRequest"/> class.</returns>
|
||||||
|
public MessageBatchRequest(List<MessageBatchRequestItem> requests)
|
||||||
|
{
|
||||||
|
if (requests.Count == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"{nameof(requests)} must not be empty.", nameof(requests));
|
||||||
|
}
|
||||||
|
|
||||||
|
Requests = requests;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
using AnthropicClient.Utils;
|
||||||
|
|
||||||
|
namespace AnthropicClient.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an item in a batch of messages.
|
||||||
|
/// </summary>
|
||||||
|
public class MessageBatchRequestItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the custom identifier for the message.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("custom_id")]
|
||||||
|
public string CustomId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message request parameters.
|
||||||
|
/// </summary>
|
||||||
|
public MessageRequest Params { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MessageBatchRequestItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="customId">The custom identifier for the message.</param>
|
||||||
|
/// <param name="messageRequest">The message request parameters.</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown when <paramref name="customId"/> is null or whitespace.</exception>
|
||||||
|
/// <exception cref="ArgumentException">Thrown when <paramref name="messageRequest"/> is null.</exception>
|
||||||
|
/// <returns>An instance of the <see cref="MessageBatchRequestItem"/> class.</returns>
|
||||||
|
public MessageBatchRequestItem(string customId, MessageRequest messageRequest)
|
||||||
|
{
|
||||||
|
ArgumentValidator.ThrowIfNullOrWhitespace(customId, nameof(customId));
|
||||||
|
ArgumentValidator.ThrowIfNull(messageRequest, nameof(messageRequest));
|
||||||
|
|
||||||
|
CustomId = customId;
|
||||||
|
Params = messageRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace AnthropicClient.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a response to a batch of messages.
|
||||||
|
/// </summary>
|
||||||
|
public class MessageBatchResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the identifier of the batch.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type of the batch.
|
||||||
|
/// </summary>
|
||||||
|
public string Type { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the processing status of the batch.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("processing_status")]
|
||||||
|
public string ProcessingStatus { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the counts of requests in the batch.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("request_counts")]
|
||||||
|
public MessageBatchRequestCounts RequestCounts { get; init; } = new MessageBatchRequestCounts();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date and time when the batch ended.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("ended_at")]
|
||||||
|
public DateTimeOffset EndedAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date and time when the batch was created.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("created_at")]
|
||||||
|
public DateTimeOffset CreatedAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date and time when the batch expires.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("expires_at")]
|
||||||
|
public DateTimeOffset ExpiresAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date and time when the batch was archived.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("archived_at")]
|
||||||
|
public DateTimeOffset ArchivedAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date and time when the batch cancellation was initiated.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("cancel_initiated_at")]
|
||||||
|
public DateTimeOffset CancelInitiatedAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the URL to the results of the batch.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("results_url")]
|
||||||
|
public string ResultsUrl { get; init; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the counts of requests in a batch of messages.
|
||||||
|
/// </summary>
|
||||||
|
public class MessageBatchRequestCounts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of requests in the batch that are processing.
|
||||||
|
/// </summary>
|
||||||
|
public int Processing { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of requests in the batch that succeeded.
|
||||||
|
/// </summary>
|
||||||
|
public int Succeeded { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of requests in the batch that errored.
|
||||||
|
/// </summary>
|
||||||
|
public int Errored { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of requests in the batch that were cancelled.
|
||||||
|
/// </summary>
|
||||||
|
public int Canceled { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of requests in the batch that expired.
|
||||||
|
/// </summary>
|
||||||
|
public int Expired { get; init; }
|
||||||
|
}
|
||||||
@@ -978,4 +978,58 @@ public class AnthropicApiClientTests : IntegrationTest
|
|||||||
result.IsSuccess.Should().BeTrue();
|
result.IsSuccess.Should().BeTrue();
|
||||||
result.Value.Should().BeOfType<AnthropicModel>();
|
result.Value.Should().BeOfType<AnthropicModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateMessageBatchAsync_WhenCalled_ItShouldReturnBatch()
|
||||||
|
{
|
||||||
|
_mockHttpMessageHandler
|
||||||
|
.WhenCreateMessageBatchRequest()
|
||||||
|
.Respond(
|
||||||
|
HttpStatusCode.OK,
|
||||||
|
"application/json",
|
||||||
|
@"{
|
||||||
|
""id"": ""msgbatch_013Zva2CMHLNnXjNJJKqJ2EF"",
|
||||||
|
""type"": ""message_batch"",
|
||||||
|
""processing_status"": ""in_progress"",
|
||||||
|
""request_counts"": {
|
||||||
|
""processing"": 100,
|
||||||
|
""succeeded"": 50,
|
||||||
|
""errored"": 30,
|
||||||
|
""canceled"": 10,
|
||||||
|
""expired"": 10
|
||||||
|
},
|
||||||
|
""ended_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""created_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""expires_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""archived_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""cancel_initiated_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""results_url"": ""https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results""
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
|
||||||
|
var request = new MessageBatchRequest([new("custom_id", new())]);
|
||||||
|
|
||||||
|
var result = await Client.CreateMessageBatchAsync(request);
|
||||||
|
|
||||||
|
result.IsSuccess.Should().BeTrue();
|
||||||
|
result.Value.Should().BeOfType<MessageBatchResponse>();
|
||||||
|
result.Value.Id.Should().Be("msgbatch_013Zva2CMHLNnXjNJJKqJ2EF");
|
||||||
|
result.Value.Type.Should().Be("message_batch");
|
||||||
|
result.Value.ProcessingStatus.Should().Be("in_progress");
|
||||||
|
result.Value.RequestCounts.Should().BeEquivalentTo(new MessageBatchRequestCounts
|
||||||
|
{
|
||||||
|
Processing = 100,
|
||||||
|
Succeeded = 50,
|
||||||
|
Errored = 30,
|
||||||
|
Canceled = 10,
|
||||||
|
Expired = 10
|
||||||
|
});
|
||||||
|
|
||||||
|
result.Value.EndedAt.Should().Be(DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"));
|
||||||
|
result.Value.CreatedAt.Should().Be(DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"));
|
||||||
|
result.Value.ExpiresAt.Should().Be(DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"));
|
||||||
|
result.Value.ArchivedAt.Should().Be(DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"));
|
||||||
|
result.Value.CancelInitiatedAt.Should().Be(DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"));
|
||||||
|
result.Value.ResultsUrl.Should().Be("https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,7 @@ public static class MockHttpMessageHandlerExtensions
|
|||||||
private const string BaseUrl = "https://api.anthropic.com/v1";
|
private const string BaseUrl = "https://api.anthropic.com/v1";
|
||||||
private static readonly string MessagesEndpoint = $"{BaseUrl}/messages";
|
private static readonly string MessagesEndpoint = $"{BaseUrl}/messages";
|
||||||
private static readonly string CountTokensEndpoint = $"{BaseUrl}/messages/count_tokens";
|
private static readonly string CountTokensEndpoint = $"{BaseUrl}/messages/count_tokens";
|
||||||
|
private static readonly string MessageBatchesEndpoint = $"{BaseUrl}/messages/batches";
|
||||||
private static readonly string ModelsEndpoint = $"{BaseUrl}/models";
|
private static readonly string ModelsEndpoint = $"{BaseUrl}/models";
|
||||||
|
|
||||||
private static MockedRequest SetupBaseRequest(
|
private static MockedRequest SetupBaseRequest(
|
||||||
@@ -64,4 +65,10 @@ public static class MockHttpMessageHandlerExtensions
|
|||||||
return mockHttpMessageHandler
|
return mockHttpMessageHandler
|
||||||
.SetupBaseRequest(HttpMethod.Get, $"{ModelsEndpoint}/{modelId}");
|
.SetupBaseRequest(HttpMethod.Get, $"{ModelsEndpoint}/{modelId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MockedRequest WhenCreateMessageBatchRequest(this MockHttpMessageHandler mockHttpMessageHandler)
|
||||||
|
{
|
||||||
|
return mockHttpMessageHandler
|
||||||
|
.SetupBaseRequest(HttpMethod.Post, MessageBatchesEndpoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
namespace AnthropicClient.Tests.Unit.Models;
|
||||||
|
|
||||||
|
public class MessageBatchRequestItemTests : SerializationTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WhenCalled_ItShouldReturnInstanceWithPropertiesSet()
|
||||||
|
{
|
||||||
|
var customId = "custom_id";
|
||||||
|
var messageRequest = new MessageRequest();
|
||||||
|
|
||||||
|
var result = new MessageBatchRequestItem(customId, messageRequest);
|
||||||
|
|
||||||
|
result.Should().BeOfType<MessageBatchRequestItem>();
|
||||||
|
result.CustomId.Should().Be(customId);
|
||||||
|
result.Params.Should().BeSameAs(messageRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData(" ")]
|
||||||
|
[InlineData(null)]
|
||||||
|
public void Constructor_WhenCalledAndCustomIdIsInvalid_ItShouldThrowException(string? customId)
|
||||||
|
{
|
||||||
|
var act = () => new MessageBatchRequestItem(customId!, new MessageRequest());
|
||||||
|
|
||||||
|
act.Should().Throw<ArgumentException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WhenCalledAndMessageRequestIsNull_ItShouldThrowException()
|
||||||
|
{
|
||||||
|
var act = () => new MessageBatchRequestItem("custom_id", null!);
|
||||||
|
|
||||||
|
act.Should().Throw<ArgumentException>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
namespace AnthropicClient.Tests.Unit.Models;
|
||||||
|
|
||||||
|
public class MessageBatchRequestTests : SerializationTest
|
||||||
|
{
|
||||||
|
private const string SampleJson = @"{
|
||||||
|
""requests"": [
|
||||||
|
{
|
||||||
|
""custom_id"": ""my-first-request"",
|
||||||
|
""params"": {
|
||||||
|
""model"": ""claude-3-5-sonnet-20241022"",
|
||||||
|
""messages"": [
|
||||||
|
{""role"": ""user"", ""content"": [{ ""text"": ""Hello, world"", ""type"": ""text"" }]}
|
||||||
|
],
|
||||||
|
""max_tokens"": 1024,
|
||||||
|
""stop_sequences"": [],
|
||||||
|
""temperature"": 0.0,
|
||||||
|
""stream"": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""custom_id"": ""my-second-request"",
|
||||||
|
""params"": {
|
||||||
|
""model"": ""claude-3-5-sonnet-20241022"",
|
||||||
|
""messages"": [
|
||||||
|
{""role"": ""user"", ""content"": [{ ""text"": ""Hi again, friend"", ""type"": ""text"" }]}
|
||||||
|
],
|
||||||
|
""max_tokens"": 1024,
|
||||||
|
""stop_sequences"": [],
|
||||||
|
""temperature"": 0.0,
|
||||||
|
""stream"": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WhenCalled_ItShouldReturnInstanceWithPropertiesSet()
|
||||||
|
{
|
||||||
|
var requests = new List<MessageBatchRequestItem> { new("custom_id", new()) };
|
||||||
|
|
||||||
|
var result = new MessageBatchRequest(requests);
|
||||||
|
|
||||||
|
result.Should().BeOfType<MessageBatchRequest>();
|
||||||
|
result.Requests.Should().BeSameAs(requests);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WhenCalledWithEmptyRequests_ItShouldThrowException()
|
||||||
|
{
|
||||||
|
var act = () => new MessageBatchRequest([]);
|
||||||
|
|
||||||
|
act.Should().Throw<ArgumentException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||||
|
{
|
||||||
|
var requests = new List<MessageBatchRequestItem>
|
||||||
|
{
|
||||||
|
new("my-first-request", new()
|
||||||
|
{
|
||||||
|
Model = "claude-3-5-sonnet-20241022",
|
||||||
|
MaxTokens = 1024,
|
||||||
|
Messages = [
|
||||||
|
new() { Role = "user", Content = [new TextContent("Hello, world")] }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
new("my-second-request", new()
|
||||||
|
{
|
||||||
|
Model = "claude-3-5-sonnet-20241022",
|
||||||
|
MaxTokens = 1024,
|
||||||
|
Messages = [
|
||||||
|
new() { Role = "user", Content = [new TextContent("Hi again, friend")] }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = new MessageBatchRequest(requests);
|
||||||
|
|
||||||
|
var json = Serialize(result);
|
||||||
|
|
||||||
|
JsonAssert.Equal(SampleJson, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
namespace AnthropicClient.Tests.Unit.Models;
|
||||||
|
|
||||||
|
public class MessageBatchResponseTests : SerializationTest
|
||||||
|
{
|
||||||
|
private const string SampleJson = @"{
|
||||||
|
""id"": ""msgbatch_013Zva2CMHLNnXjNJJKqJ2EF"",
|
||||||
|
""type"": ""message_batch"",
|
||||||
|
""processing_status"": ""in_progress"",
|
||||||
|
""request_counts"": {
|
||||||
|
""processing"": 100,
|
||||||
|
""succeeded"": 50,
|
||||||
|
""errored"": 30,
|
||||||
|
""canceled"": 10,
|
||||||
|
""expired"": 10
|
||||||
|
},
|
||||||
|
""ended_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""created_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""expires_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""archived_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""cancel_initiated_at"": ""2024-08-20T18:37:24.100435Z"",
|
||||||
|
""results_url"": ""https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results""
|
||||||
|
}";
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WhenCalled_ItShouldReturnInstanceWithPropertiesSet()
|
||||||
|
{
|
||||||
|
var result = new MessageBatchResponse();
|
||||||
|
|
||||||
|
result.Should().BeOfType<MessageBatchResponse>();
|
||||||
|
result.Id.Should().BeEmpty();
|
||||||
|
result.Type.Should().BeEmpty();
|
||||||
|
result.ProcessingStatus.Should().BeEmpty();
|
||||||
|
result.RequestCounts.Should().BeEquivalentTo(new MessageBatchRequestCounts());
|
||||||
|
result.EndedAt.Should().Be(DateTimeOffset.MinValue);
|
||||||
|
result.CreatedAt.Should().Be(DateTimeOffset.MinValue);
|
||||||
|
result.ExpiresAt.Should().Be(DateTimeOffset.MinValue);
|
||||||
|
result.ArchivedAt.Should().Be(DateTimeOffset.MinValue);
|
||||||
|
result.CancelInitiatedAt.Should().Be(DateTimeOffset.MinValue);
|
||||||
|
result.ResultsUrl.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void JsonSerialization_WhenDeserialized_ItShouldHaveExpectedValues()
|
||||||
|
{
|
||||||
|
var result = Deserialize<MessageBatchResponse>(SampleJson);
|
||||||
|
|
||||||
|
result.Should().BeEquivalentTo(new MessageBatchResponse
|
||||||
|
{
|
||||||
|
Id = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF",
|
||||||
|
Type = "message_batch",
|
||||||
|
ProcessingStatus = "in_progress",
|
||||||
|
RequestCounts = new MessageBatchRequestCounts
|
||||||
|
{
|
||||||
|
Processing = 100,
|
||||||
|
Succeeded = 50,
|
||||||
|
Errored = 30,
|
||||||
|
Canceled = 10,
|
||||||
|
Expired = 10
|
||||||
|
},
|
||||||
|
EndedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
CreatedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ExpiresAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ArchivedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
CancelInitiatedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ResultsUrl = "https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||||
|
{
|
||||||
|
var expectedJson = @"{
|
||||||
|
""id"": ""msgbatch_013Zva2CMHLNnXjNJJKqJ2EF"",
|
||||||
|
""type"": ""message_batch"",
|
||||||
|
""processing_status"": ""in_progress"",
|
||||||
|
""request_counts"": {
|
||||||
|
""processing"": 100,
|
||||||
|
""succeeded"": 50,
|
||||||
|
""errored"": 30,
|
||||||
|
""canceled"": 10,
|
||||||
|
""expired"": 10
|
||||||
|
},
|
||||||
|
""ended_at"": ""2024-08-20T18:37:24.100435+00:00"",
|
||||||
|
""created_at"": ""2024-08-20T18:37:24.100435+00:00"",
|
||||||
|
""expires_at"": ""2024-08-20T18:37:24.100435+00:00"",
|
||||||
|
""archived_at"": ""2024-08-20T18:37:24.100435+00:00"",
|
||||||
|
""cancel_initiated_at"": ""2024-08-20T18:37:24.100435+00:00"",
|
||||||
|
""results_url"": ""https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results""
|
||||||
|
}";
|
||||||
|
|
||||||
|
var result = Serialize(new MessageBatchResponse
|
||||||
|
{
|
||||||
|
Id = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF",
|
||||||
|
Type = "message_batch",
|
||||||
|
ProcessingStatus = "in_progress",
|
||||||
|
RequestCounts = new MessageBatchRequestCounts
|
||||||
|
{
|
||||||
|
Processing = 100,
|
||||||
|
Succeeded = 50,
|
||||||
|
Errored = 30,
|
||||||
|
Canceled = 10,
|
||||||
|
Expired = 10
|
||||||
|
},
|
||||||
|
EndedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
CreatedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ExpiresAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ArchivedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
CancelInitiatedAt = DateTimeOffset.Parse("2024-08-20T18:37:24.100435Z"),
|
||||||
|
ResultsUrl = "https://api.anthropic.com/v1/messages/batches/msgbatch_013Zva2CMHLNnXjNJJKqJ2EF/results"
|
||||||
|
});
|
||||||
|
|
||||||
|
JsonAssert.Equal(expectedJson, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user