feat: add CancelMessageBatchAsync method and corresponding tests
This commit is contained in:
@@ -55,6 +55,13 @@ public interface IAnthropicApiClient
|
|||||||
/// <returns>An asynchronous enumerable that yields the response as an <see cref="AnthropicResult{T}"/> where T is <see cref="Page{T}"/> where T is <see cref="MessageBatchResponse"/>.</returns>
|
/// <returns>An asynchronous enumerable that yields the response as an <see cref="AnthropicResult{T}"/> where T is <see cref="Page{T}"/> where T is <see cref="MessageBatchResponse"/>.</returns>
|
||||||
IAsyncEnumerable<AnthropicResult<Page<MessageBatchResponse>>> ListAllMessageBatchesAsync(int limit = 20);
|
IAsyncEnumerable<AnthropicResult<Page<MessageBatchResponse>>> ListAllMessageBatchesAsync(int limit = 20);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancels a message batch asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batchId">The ID of the message batch to cancel.</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>> CancelMessageBatchAsync(string batchId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the results of a message batch asynchronously.
|
/// Gets the results of a message batch asynchronously.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -384,6 +391,24 @@ public class AnthropicApiClient : IAnthropicApiClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<AnthropicResult<MessageBatchResponse>> CancelMessageBatchAsync(string batchId)
|
||||||
|
{
|
||||||
|
var endpoint = $"{MessageBatchesEndpoint}/{batchId}/cancel";
|
||||||
|
var response = await SendRequestAsync(endpoint, HttpMethod.Post);
|
||||||
|
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<IAsyncEnumerable<MessageBatchResultItem>>> GetMessageBatchResultsAsync(string batchId)
|
public async Task<AnthropicResult<IAsyncEnumerable<MessageBatchResultItem>>> GetMessageBatchResultsAsync(string batchId)
|
||||||
{
|
{
|
||||||
@@ -533,9 +558,10 @@ public class AnthropicApiClient : IAnthropicApiClient
|
|||||||
return new ToolCall(tool, toolUse);
|
return new ToolCall(tool, toolUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendRequestAsync(string endpoint)
|
private async Task<HttpResponseMessage> SendRequestAsync(string endpoint, HttpMethod? method = null)
|
||||||
{
|
{
|
||||||
return await _httpClient.GetAsync(endpoint);
|
var request = new HttpRequestMessage(method ?? HttpMethod.Get, endpoint);
|
||||||
|
return await _httpClient.SendAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendRequestAsync<T>(string endpoint, T request)
|
private async Task<HttpResponseMessage> SendRequestAsync<T>(string endpoint, T request)
|
||||||
|
|||||||
@@ -1282,26 +1282,26 @@ public class AnthropicApiClientTests : IntegrationTest
|
|||||||
var result = await Client.GetMessageBatchAsync(batchId);
|
var result = await Client.GetMessageBatchAsync(batchId);
|
||||||
|
|
||||||
result.IsSuccess.Should().BeTrue();
|
result.IsSuccess.Should().BeTrue();
|
||||||
result.Value.Should().BeOfType<MessageBatchResponse>();
|
result.Value.Should().BeEquivalentTo(new MessageBatchResponse()
|
||||||
result.Value.Id.Should().Be("msgbatch_013Zva2CMHLNnXjNJJKqJ2EF");
|
{
|
||||||
result.Value.Type.Should().Be("message_batch");
|
Id = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF",
|
||||||
result.Value.ProcessingStatus.Should().Be("in_progress");
|
Type = "message_batch",
|
||||||
result.Value.RequestCounts.Should().BeEquivalentTo(new MessageBatchRequestCounts
|
ProcessingStatus = "in_progress",
|
||||||
|
RequestCounts = new MessageBatchRequestCounts
|
||||||
{
|
{
|
||||||
Processing = 100,
|
Processing = 100,
|
||||||
Succeeded = 50,
|
Succeeded = 50,
|
||||||
Errored = 30,
|
Errored = 30,
|
||||||
Canceled = 10,
|
Canceled = 10,
|
||||||
Expired = 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"
|
||||||
});
|
});
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -1823,4 +1823,85 @@ public class AnthropicApiClientTests : IntegrationTest
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CancelMessageBatchAsync_WhenCalled_ItShouldReturnBatch()
|
||||||
|
{
|
||||||
|
var batchId = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF";
|
||||||
|
|
||||||
|
_mockHttpMessageHandler
|
||||||
|
.WhenCancelMessageBatchRequest(batchId)
|
||||||
|
.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 result = await Client.CancelMessageBatchAsync(batchId);
|
||||||
|
|
||||||
|
result.IsSuccess.Should().BeTrue();
|
||||||
|
result.Value.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 async Task CancelMessageBatchAsync_WhenCalledAndFails_ItShouldReturnError()
|
||||||
|
{
|
||||||
|
var batchId = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF";
|
||||||
|
|
||||||
|
_mockHttpMessageHandler
|
||||||
|
.WhenCancelMessageBatchRequest(batchId)
|
||||||
|
.Respond(
|
||||||
|
HttpStatusCode.BadRequest,
|
||||||
|
"application/json",
|
||||||
|
@"{
|
||||||
|
""type"": ""error"",
|
||||||
|
""error"": {
|
||||||
|
""type"": ""invalid_request_error"",
|
||||||
|
""message"": ""batch: batch not found""
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = await Client.CancelMessageBatchAsync(batchId);
|
||||||
|
|
||||||
|
result.IsSuccess.Should().BeFalse();
|
||||||
|
result.Error.Should().BeOfType<AnthropicError>();
|
||||||
|
result.Error.Error.Should().BeOfType<InvalidRequestError>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -91,4 +91,10 @@ public static class MockHttpMessageHandlerExtensions
|
|||||||
return mockHttpMessageHandler
|
return mockHttpMessageHandler
|
||||||
.SetupBaseRequest(HttpMethod.Get, MessageBatchesEndpoint);
|
.SetupBaseRequest(HttpMethod.Get, MessageBatchesEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MockedRequest WhenCancelMessageBatchRequest(this MockHttpMessageHandler mockHttpMessageHandler, string batchId)
|
||||||
|
{
|
||||||
|
return mockHttpMessageHandler
|
||||||
|
.SetupBaseRequest(HttpMethod.Post, $"{MessageBatchesEndpoint}/{batchId}/cancel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user