From c4d4d8a15bb690ae2b766a8f797b9e49f6965e60 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:42:42 -0600 Subject: [PATCH 1/6] feat: add content type --- src/AnthropicClient/Models/ContentType.cs | 5 ++++ .../Unit/Models/ContentTypeTests.cs | 28 ++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/AnthropicClient/Models/ContentType.cs b/src/AnthropicClient/Models/ContentType.cs index e34013c..b84fb21 100644 --- a/src/AnthropicClient/Models/ContentType.cs +++ b/src/AnthropicClient/Models/ContentType.cs @@ -24,4 +24,9 @@ public static class ContentType /// Represents the tool result content type. /// public const string ToolResult = "tool_result"; + + /// + /// Represents the document content type. + /// + public const string Document = "document"; } \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Unit/Models/ContentTypeTests.cs b/tests/AnthropicClient.Tests/Unit/Models/ContentTypeTests.cs index 51362fb..d072118 100644 --- a/tests/AnthropicClient.Tests/Unit/Models/ContentTypeTests.cs +++ b/tests/AnthropicClient.Tests/Unit/Models/ContentTypeTests.cs @@ -5,40 +5,30 @@ public class ContentTypeTests [Fact] public void Text_WhenCalled_ItShouldReturnText() { - var expected = "text"; - - var actual = ContentType.Text; - - actual.Should().Be(expected); + ContentType.Text.Should().Be("text"); } [Fact] public void Image_WhenCalled_ItShouldReturnImage() { - var expected = "image"; - - var actual = ContentType.Image; - - actual.Should().Be(expected); + ContentType.Image.Should().Be("image"); } [Fact] public void ToolUse_WhenCalled_ItShouldReturnToolUse() { - var expected = "tool_use"; - - var actual = ContentType.ToolUse; - - actual.Should().Be(expected); + ContentType.ToolUse.Should().Be("tool_use"); } [Fact] public void ToolResult_WhenCalled_ItShouldReturnToolResult() { - var expected = "tool_result"; + ContentType.ToolResult.Should().Be("tool_result"); + } - var actual = ContentType.ToolResult; - - actual.Should().Be(expected); + [Fact] + public void Document_WhenCalled_ItShouldReturnDocument() + { + ContentType.Document.Should().Be("document"); } } \ No newline at end of file From f3a7040cb929ac55df2b8369a26bb1b1a8e29fc8 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:43:21 -0600 Subject: [PATCH 2/6] feat: add model for DocumentContent and DocumentSource --- src/AnthropicClient/Json/ContentConverter.cs | 1 + src/AnthropicClient/Models/DocumentContent.cs | 56 +++++++++ src/AnthropicClient/Models/DocumentSource.cs | 49 ++++++++ .../Unit/Models/DocumentContentTests.cs | 119 ++++++++++++++++++ .../Unit/Models/DocumentSourceTests.cs | 49 ++++++++ 5 files changed, 274 insertions(+) create mode 100644 src/AnthropicClient/Models/DocumentContent.cs create mode 100644 src/AnthropicClient/Models/DocumentSource.cs create mode 100644 tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs create mode 100644 tests/AnthropicClient.Tests/Unit/Models/DocumentSourceTests.cs diff --git a/src/AnthropicClient/Json/ContentConverter.cs b/src/AnthropicClient/Json/ContentConverter.cs index e0183d4..d7fbd14 100644 --- a/src/AnthropicClient/Json/ContentConverter.cs +++ b/src/AnthropicClient/Json/ContentConverter.cs @@ -16,6 +16,7 @@ class ContentConverter : JsonConverter { ContentType.Text => JsonSerializer.Deserialize(root.GetRawText(), options)!, ContentType.Image => JsonSerializer.Deserialize(root.GetRawText(), options)!, + ContentType.Document => JsonSerializer.Deserialize(root.GetRawText(), options)!, ContentType.ToolUse => JsonSerializer.Deserialize(root.GetRawText(), options)!, ContentType.ToolResult => JsonSerializer.Deserialize(root.GetRawText(), options)!, _ => throw new JsonException($"Unknown content type: {type}") diff --git a/src/AnthropicClient/Models/DocumentContent.cs b/src/AnthropicClient/Models/DocumentContent.cs new file mode 100644 index 0000000..1389d84 --- /dev/null +++ b/src/AnthropicClient/Models/DocumentContent.cs @@ -0,0 +1,56 @@ +using System.Text.Json.Serialization; + +using AnthropicClient.Utils; + +namespace AnthropicClient.Models; + +/// +/// Represents content from a document that is part of a message. +/// +public class DocumentContent : Content +{ + /// + /// Gets the source of the document. + /// + public DocumentSource Source { get; init; } = new(); + + [JsonConstructor] + internal DocumentContent() + { + } + + private void Validate(string mediaType, string data) + { + ArgumentValidator.ThrowIfNull(mediaType, nameof(mediaType)); + ArgumentValidator.ThrowIfNull(data, nameof(data)); + } + + /// + /// Initializes a new instance of the class. + /// + /// The media type of the document. + /// The data of the document. + /// Thrown when the media type or data is null. + /// A new instance of the class. + public DocumentContent(string mediaType, string data) : base(ContentType.Document) + { + Validate(mediaType, data); + + Source = new(mediaType, data); + } + + /// + /// Initializes a new instance of the class. + /// + /// The media type of the document. + /// The data of the document. + /// The cache control to be used for the content. + /// A new instance of the class. + /// Thrown when the media type, data, or cache control is null. + public DocumentContent(string mediaType, string data, CacheControl cacheControl) : base(ContentType.Document, cacheControl) + { + Validate(mediaType, data); + + Source = new(mediaType, data); + } +} \ No newline at end of file diff --git a/src/AnthropicClient/Models/DocumentSource.cs b/src/AnthropicClient/Models/DocumentSource.cs new file mode 100644 index 0000000..e18f978 --- /dev/null +++ b/src/AnthropicClient/Models/DocumentSource.cs @@ -0,0 +1,49 @@ +using System.Text.Json.Serialization; + +using AnthropicClient.Utils; + +namespace AnthropicClient.Models; + +/// +/// Represents a document source. +/// +public class DocumentSource +{ + /// + /// Gets the media type of the document. + /// + [JsonPropertyName("media_type")] + public string MediaType { get; init; } = string.Empty; + + /// + /// Gets the data of the document. + /// + public string Data { get; init; } = string.Empty; + + /// + /// Gets the type of encoding of the document data. + /// + public string Type { get; init; } = "base64"; + + [JsonConstructor] + internal DocumentSource() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The media type of the document. + /// The data of the document. + /// Thrown when the media type is invalid. + /// Thrown when the media type or data is null. + /// A new instance of the class. + public DocumentSource(string mediaType, string data) + { + ArgumentValidator.ThrowIfNull(mediaType, nameof(mediaType)); + ArgumentValidator.ThrowIfNull(data, nameof(data)); + + MediaType = mediaType; + Data = data; + } +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs b/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs new file mode 100644 index 0000000..cec42f1 --- /dev/null +++ b/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs @@ -0,0 +1,119 @@ +namespace AnthropicClient.Tests.Unit.Models; + +public class DocumentContentTests : SerializationTest +{ + private readonly string _testJson = @"{ + ""source"": { + ""media_type"": ""application/pdf"", + ""data"": ""data"", + ""type"": ""base64"" + }, + ""type"": ""document"" + }"; + + private readonly string _testJsonWithCacheControl = @"{ + ""source"": { + ""media_type"": ""application/pdf"", + ""data"": ""data"", + ""type"": ""base64"" + }, + ""cache_control"": { ""type"": ""ephemeral"" }, + ""type"": ""document"" + }"; + + [Fact] + public void Constructor_WhenCalled_ItShouldInitializeSource() + { + var expectedMediaType = "application/pdf"; + var expectedData = "data"; + + var result = new DocumentContent(expectedMediaType, expectedData); + + result.Source.Should().BeEquivalentTo(new DocumentSource(expectedMediaType, expectedData)); + } + + [Fact] + public void Constructor_WhenCalledAndMediaTypeIsNull_ItShouldThrowArgumentNullException() + { + var expectedData = "data"; + + var action = () => new DocumentContent(null!, expectedData); + + action.Should().Throw(); + } + + [Fact] + public void Constructor_WhenCalledAndDataIsNull_ItShouldThrowArgumentNullException() + { + var expectedMediaType = "application/pdf"; + + var action = () => new DocumentContent(expectedMediaType, null!); + + action.Should().Throw(); + } + + [Fact] + public void Constructor_WhenCalledWithCacheControl_ItShouldInitializeSourceAndCacheControl() + { + var expectedMediaType = "application/pdf"; + var expectedData = "data"; + var cacheControl = new EphemeralCacheControl(); + + var result = new DocumentContent(expectedMediaType, expectedData, cacheControl); + + result.Source.Should().BeEquivalentTo(new DocumentSource(expectedMediaType, expectedData)); + result.CacheControl.Should().BeSameAs(cacheControl); + } + + [Fact] + public void Constructor_WhenCalledWithCacheControlAndMediaTypeIsNull_ItShouldThrowArgumentNullException() + { + var expectedData = "data"; + var cacheControl = new EphemeralCacheControl(); + + var action = () => new DocumentContent(null!, expectedData, cacheControl); + + action.Should().Throw(); + } + + [Fact] + public void Constructor_WhenCalledWithCacheControlAndDataIsNull_ItShouldThrowArgumentNullException() + { + var expectedMediaType = "application/pdf"; + var cacheControl = new EphemeralCacheControl(); + + var action = () => new DocumentContent(expectedMediaType, null!, cacheControl); + + action.Should().Throw(); + } + + [Fact] + public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape() + { + var content = new DocumentContent("application/pdf", "data"); + + var actual = Serialize(content); + + JsonAssert.Equal(_testJson, actual); + } + + [Fact] + public void JsonSerialization_WhenSerializedWithCacheControl_ItShouldHaveExpectedShape() + { + var content = new DocumentContent("application/pdf", "data", new EphemeralCacheControl()); + + var actual = Serialize(content); + + JsonAssert.Equal(_testJsonWithCacheControl, actual); + } + + [Fact] + public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedShape() + { + var expected = new DocumentContent("application/pdf", "data"); + + var actual = Deserialize(_testJson); + + actual.Should().BeEquivalentTo(expected); + } +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Unit/Models/DocumentSourceTests.cs b/tests/AnthropicClient.Tests/Unit/Models/DocumentSourceTests.cs new file mode 100644 index 0000000..60e2ec3 --- /dev/null +++ b/tests/AnthropicClient.Tests/Unit/Models/DocumentSourceTests.cs @@ -0,0 +1,49 @@ +namespace AnthropicClient.Tests.Unit.Models; + +public class DocumentSourceTests +{ + [Fact] + public void Constructor_WhenCalledWithValidArguments_ItShouldSetProperties() + { + var mediaType = "application/pdf"; + var data = "base64data"; + + var source = new DocumentSource(mediaType, data); + + source.MediaType.Should().Be(mediaType); + source.Data.Should().Be(data); + } + + [Fact] + public void Constructor_WhenCalledWithNullMediaType_ItShouldThrowArgumentNullException() + { + string? mediaType = null; + var data = "base64data"; + + var action = () => new DocumentSource(mediaType!, data); + + action.Should().Throw(); + } + + [Fact] + public void Constructor_WhenCalledWithNullData_ItShouldThrowArgumentNullException() + { + var mediaType = "application/pdf"; + string? data = null; + + var action = () => new DocumentSource(mediaType, data!); + + action.Should().Throw(); + } + + [Fact] + public void Constructor_WhenCalled_ItShouldHaveTypePropertySetToBase64() + { + var mediaType = "application/pdf"; + var data = "base64data"; + + var source = new DocumentSource(mediaType, data); + + source.Type.Should().Be("base64"); + } +} \ No newline at end of file From fe984d517df13ab35dfa625619bf333b588cd987 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:43:41 -0600 Subject: [PATCH 3/6] tests: add end to end test using pdf support --- .../EndToEnd/AnthropicApiClientTests.cs | 77 ++++++++++++++++++ .../AnthropicClient.Tests/Files/addendum.pdf | Bin 0 -> 56910 bytes 2 files changed, 77 insertions(+) create mode 100644 tests/AnthropicClient.Tests/Files/addendum.pdf diff --git a/tests/AnthropicClient.Tests/EndToEnd/AnthropicApiClientTests.cs b/tests/AnthropicClient.Tests/EndToEnd/AnthropicApiClientTests.cs index 5b7a3cd..d66e39e 100644 --- a/tests/AnthropicClient.Tests/EndToEnd/AnthropicApiClientTests.cs +++ b/tests/AnthropicClient.Tests/EndToEnd/AnthropicApiClientTests.cs @@ -222,4 +222,81 @@ public class ClientTests(ConfigurationFixture configFixture) : EndToEndTest(conf resultTwo.Value.Content.Should().NotBeNullOrEmpty(); resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0); } + + [Fact] + public async Task CreateMessageAsync_WhenProvidedWithPDF_ItShouldReturnResponse() + { + var pdfPath = GetTestFilePath("addendum.pdf"); + var bytes = await File.ReadAllBytesAsync(pdfPath); + var base64Data = Convert.ToBase64String(bytes); + + var request = new MessageRequest( + model: AnthropicModels.Claude35Sonnet, + messages: [ + new(MessageRole.User, [new TextContent("What is the title of this paper?")]), + new(MessageRole.User, [new DocumentContent("application/pdf", base64Data)]) + ] + ); + + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25"); + var client = CreateClient(httpClient); + + var result = await client.CreateMessageAsync(request); + + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeOfType(); + result.Value.Content.Should().NotBeNullOrEmpty(); + + var text = result.Value.Content.Aggregate("", (acc, content) => + { + if (content is TextContent textContent) + { + acc += textContent.Text; + } + + return acc; + }); + + text.Should().Contain("Model Card Addendum: Claude 3.5 Haiku and Upgraded Claude 3.5 Sonnet"); + } + + [Fact] + public async Task CreateMessageAsync_WhenProvidedWithPDFWithCacheControl_ItShouldUseCache() + { + var pdfPath = GetTestFilePath("addendum.pdf"); + var bytes = await File.ReadAllBytesAsync(pdfPath); + var base64Data = Convert.ToBase64String(bytes); + + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25, prompt-caching-2024-07-31"); + var client = CreateClient(httpClient); + + var request = new MessageRequest( + model: AnthropicModels.Claude35Sonnet, + messages: [ + new(MessageRole.User, [ + new DocumentContent("application/pdf", base64Data, new EphemeralCacheControl()), + new TextContent("What is the title of this paper?") + ]), + ] + ); + + var resultOne = await client.CreateMessageAsync(request); + + resultOne.IsSuccess.Should().BeTrue(); + resultOne.Value.Should().BeOfType(); + resultOne.Value.Content.Should().NotBeNullOrEmpty(); + resultOne.Value.Usage.Should().Match(u => u.CacheCreationInputTokens > 0 || u.CacheReadInputTokens > 0); + + request.Messages.Add(new(MessageRole.Assistant, resultOne.Value.Content)); + request.Messages.Add(new(MessageRole.User, [new TextContent("What is the main theme of this paper?")])); + + var resultTwo = await client.CreateMessageAsync(request); + + resultTwo.IsSuccess.Should().BeTrue(); + resultTwo.Value.Should().BeOfType(); + resultTwo.Value.Content.Should().NotBeNullOrEmpty(); + resultTwo.Value.Usage.CacheReadInputTokens.Should().BeGreaterThan(0); + } } \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Files/addendum.pdf b/tests/AnthropicClient.Tests/Files/addendum.pdf new file mode 100644 index 0000000000000000000000000000000000000000..30d56ec07808b3a29cbd97bb746346f70bf6d74a GIT binary patch literal 56910 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 literal 0 HcmV?d00001 From 3de38ee5cfeda844b15974a67cd515eaf0f3165f Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:44:21 -0600 Subject: [PATCH 4/6] docs: add info about pdf support to README.md --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/README.md b/README.md index e23d001..a03e6a3 100644 --- a/README.md +++ b/README.md @@ -847,3 +847,66 @@ foreach (var content in response.Value.Content) } } ``` + +### PDF Support + +Anthropic has recently introduced a feature called [PDF Support](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support) that allows Claude to support PDF input and understand both text and visual content within documents. . This feature is covered in depth in [Anthropic's API Documentation](https://docs.anthropic.com/en/docs/build-with-claude/pdf-support). + +> [!NOTE] +> This feature is in beta and requires you to set an `anthropic-beta` header on your requests to use it. +> The value of the header should be `pdfs-2024-09-25`. + +When using this library you can opt-in to PDF support by adding the required header to the `HttpClient` instance you provide to the `AnthropicApiClient` constructor. + +```csharp +using AnthropicClient; + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25"); + +var client = new AnthropicApiClient(apiKey, httpClient); +``` + +PDF support can be used to provide a PDF document as input to the model. This can be used to provide additional context to the model or to ask for additional information from the model. This library aims to make using PDF support convenient by allowing you to provide the PDF document you want Anthropic's models to consider for use when creating a message. + +#### PDF Document + +You can provide a PDF document by providing its base64 encoded content as a `DocumentContent` instance in the list of messages in the `MessageRequest` or `StreamMessageRequest` constructor. + +```csharp +using AnthropicClient; +using AnthropicClient.Models; + +var request = new MessageRequest( + model: AnthropicModels.Claude35Sonnet, + messages: [ + new(MessageRole.User, [new TextContent("What is the title of this paper?")]), + new(MessageRole.User, [new DocumentContent("application/pdf", base64Data)]) + ] +); + +var httpClient = new HttpClient(); +httpClient.DefaultRequestHeaders.Add("anthropic-beta", "pdfs-2024-09-25"); + +var client = new AnthropicApiClient(apiKey, httpClient); + +var response = await client.CreateMessageAsync(request); + +if (response.IsSuccess is false) +{ + Console.WriteLine("Failed to create message"); + Console.WriteLine("Error Type: {0}", response.Error.Error.Type); + Console.WriteLine("Error Message: {0}", response.Error.Error.Message); + return; +} + +foreach (var content in response.Value.Content) +{ + switch (content) + { + case TextContent textContent: + Console.WriteLine(textContent.Text); + break; + } +} +``` From c66dc81df31df7aea14793741841da5d2f1341f8 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:55:56 -0600 Subject: [PATCH 5/6] tests: add a test for converting DocumentContent --- .../Integration/AnthropicApiClientTests.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs index 5272be0..ab116ec 100644 --- a/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs +++ b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs @@ -359,4 +359,63 @@ public class AnthropicApiClientTests : IntegrationTest ) )); } + + [Fact] + public async Task CreateMessageAsync_WhenCalledAndMessageCreatedWithDocumentContent_ItShouldReturnMessage() + { + _mockHttpMessageHandler + .WhenCreateMessageRequest() + .Respond( + HttpStatusCode.OK, + "application/json", + @"{ + ""content"": [ + { + ""text"": ""It is a PDF"", + ""type"": ""text"" + } + ], + ""id"": ""msg_013Zva2CMHLNnXjNJJKqJ2EF"", + ""model"": ""claude-3-5-sonnet-20240620"", + ""role"": ""assistant"", + ""stop_reason"": ""end_turn"", + ""stop_sequence"": null, + ""type"": ""message"", + ""usage"": { + ""input_tokens"": 10, + ""output_tokens"": 25 + } + }" + ); + + var request = new MessageRequest( + model: AnthropicModels.Claude35Sonnet, + messages: [ + new(MessageRole.User, [new TextContent("What is this?")]), + new(MessageRole.User, [new DocumentContent("application/pdf", "data")]) + ] + ); + + var result = await Client.CreateMessageAsync(request); + + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeOfType(); + + var message = result.Value; + message.Id.Should().Be("msg_013Zva2CMHLNnXjNJJKqJ2EF"); + message.Model.Should().Be("claude-3-5-sonnet-20240620"); + message.Role.Should().Be("assistant"); + message.StopReason.Should().Be("end_turn"); + message.StopSequence.Should().BeNull(); + message.Type.Should().Be("message"); + message.Usage.InputTokens.Should().Be(10); + message.Usage.OutputTokens.Should().Be(25); + message.Content.Should().HaveCount(1); + message.ToolCall.Should().BeNull(); + + var textContent = message.Content[0]; + textContent.Should().BeOfType(); + textContent.As().Text.Should().Be("It is a PDF"); + textContent.As().Type.Should().Be("text"); + } } \ No newline at end of file From dc9755cbb8a51bf33d182789e7b4239621ab4c5f Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:59:45 -0600 Subject: [PATCH 6/6] chore: run dotnet format --- .../Integration/AnthropicApiClientTests.cs | 2 +- tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs index ab116ec..55a22e2 100644 --- a/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs +++ b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs @@ -360,7 +360,7 @@ public class AnthropicApiClientTests : IntegrationTest )); } - [Fact] + [Fact] public async Task CreateMessageAsync_WhenCalledAndMessageCreatedWithDocumentContent_ItShouldReturnMessage() { _mockHttpMessageHandler diff --git a/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs b/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs index cec42f1..99525d5 100644 --- a/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs +++ b/tests/AnthropicClient.Tests/Unit/Models/DocumentContentTests.cs @@ -60,7 +60,7 @@ public class DocumentContentTests : SerializationTest var cacheControl = new EphemeralCacheControl(); var result = new DocumentContent(expectedMediaType, expectedData, cacheControl); - + result.Source.Should().BeEquivalentTo(new DocumentSource(expectedMediaType, expectedData)); result.CacheControl.Should().BeSameAs(cacheControl); }