diff --git a/Anthropic.SDK.Tests/Anthropic.SDK.Tests.csproj b/Anthropic.SDK.Tests/Anthropic.SDK.Tests.csproj index c53b35c..3920640 100644 --- a/Anthropic.SDK.Tests/Anthropic.SDK.Tests.csproj +++ b/Anthropic.SDK.Tests/Anthropic.SDK.Tests.csproj @@ -33,18 +33,18 @@ - - - - - - - + + + + + + + - - - - + + + + diff --git a/Anthropic.SDK.Tests/ChatOptionsExtensionsTests.cs b/Anthropic.SDK.Tests/ChatOptionsExtensionsTests.cs index 8fc537c..eff3ebe 100644 --- a/Anthropic.SDK.Tests/ChatOptionsExtensionsTests.cs +++ b/Anthropic.SDK.Tests/ChatOptionsExtensionsTests.cs @@ -26,7 +26,7 @@ public void WithThinking_SetsThinkingParameters() var thinkingParams = options.GetThinkingParameters(); Assert.IsNotNull(thinkingParams); Assert.AreEqual(budgetTokens, thinkingParams.BudgetTokens); - Assert.AreEqual("enabled", thinkingParams.Type); + Assert.AreEqual(ThinkingType.enabled, thinkingParams.Type); Assert.IsFalse(thinkingParams.UseInterleavedThinking); } @@ -63,7 +63,7 @@ public void WithInterleavedThinking_SetsInterleavedThinkingParameters() var thinkingParams = options.GetThinkingParameters(); Assert.IsNotNull(thinkingParams); Assert.AreEqual(budgetTokens, thinkingParams.BudgetTokens); - Assert.AreEqual("enabled", thinkingParams.Type); + Assert.AreEqual(ThinkingType.enabled, thinkingParams.Type); Assert.IsTrue(thinkingParams.UseInterleavedThinking); } @@ -291,7 +291,7 @@ public void ChatClientHelper_MapsThinkingParametersCorrectly() // Assert Assert.IsNotNull(messageParams.Thinking); Assert.AreEqual(3000, messageParams.Thinking.BudgetTokens); - Assert.AreEqual("enabled", messageParams.Thinking.Type); + Assert.AreEqual(ThinkingType.enabled, messageParams.Thinking.Type); Assert.IsFalse(messageParams.Thinking.UseInterleavedThinking); Assert.AreEqual(AnthropicModels.Claude37Sonnet, messageParams.Model); Assert.AreEqual(4096, messageParams.MaxTokens); @@ -319,10 +319,254 @@ public void ChatClientHelper_MapsInterleavedThinkingParametersCorrectly() // Assert Assert.IsNotNull(messageParams.Thinking); Assert.AreEqual(8000, messageParams.Thinking.BudgetTokens); - Assert.AreEqual("enabled", messageParams.Thinking.Type); + Assert.AreEqual(ThinkingType.enabled, messageParams.Thinking.Type); Assert.IsTrue(messageParams.Thinking.UseInterleavedThinking); Assert.AreEqual(AnthropicModels.Claude37Sonnet, messageParams.Model); Assert.AreEqual(4096, messageParams.MaxTokens); } + + [TestMethod] + public void WithAdaptiveThinking_SetsAdaptiveType() + { + // Arrange + var options = new ChatOptions(); + + // Act + var result = options.WithAdaptiveThinking(); + + // Assert + Assert.AreSame(options, result); + var thinkingParams = options.GetThinkingParameters(); + Assert.IsNotNull(thinkingParams); + Assert.AreEqual(ThinkingType.adaptive, thinkingParams.Type); + Assert.IsNull(thinkingParams.BudgetTokens); + Assert.IsNull(thinkingParams.Effort); + } + + [TestMethod] + public void WithAdaptiveThinking_WithEffort_SetsEffortAndAdaptiveType() + { + // Arrange + var options = new ChatOptions(); + + // Act + var result = options.WithAdaptiveThinking(ThinkingEffort.medium); + + // Assert + Assert.AreSame(options, result); + var thinkingParams = options.GetThinkingParameters(); + Assert.IsNotNull(thinkingParams); + Assert.AreEqual(ThinkingType.adaptive, thinkingParams.Type); + Assert.AreEqual(ThinkingEffort.medium, thinkingParams.Effort); + Assert.IsNull(thinkingParams.BudgetTokens); + } + + [TestMethod] + public void WithAdaptiveThinking_NullOptions_ThrowsArgumentNullException() + { + // Arrange + ChatOptions options = null; + + // Act & Assert + Assert.Throws(() => options.WithAdaptiveThinking()); + Assert.Throws(() => options.WithAdaptiveThinking(ThinkingEffort.high)); + } + + [TestMethod] + public void WithAdaptiveThinking_FluentChaining_Works() + { + // Arrange & Act + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + Temperature = 1.0f + }.WithAdaptiveThinking(ThinkingEffort.high); + + // Assert + Assert.AreEqual(AnthropicModels.Claude46Sonnet, options.ModelId); + Assert.AreEqual(16000, options.MaxOutputTokens); + Assert.AreEqual(1.0f, options.Temperature); + + var thinkingParams = options.GetThinkingParameters(); + Assert.IsNotNull(thinkingParams); + Assert.AreEqual(ThinkingType.adaptive, thinkingParams.Type); + Assert.AreEqual(ThinkingEffort.high, thinkingParams.Effort); + } + + [TestMethod] + public void WithAdaptiveThinking_OverwritesPreviousThinkingParameters() + { + // Arrange + var options = new ChatOptions(); + options.WithThinking(3000); + + // Act + options.WithAdaptiveThinking(ThinkingEffort.medium); + + // Assert + var thinkingParams = options.GetThinkingParameters(); + Assert.IsNotNull(thinkingParams); + Assert.AreEqual(ThinkingType.adaptive, thinkingParams.Type); + Assert.AreEqual(ThinkingEffort.medium, thinkingParams.Effort); + Assert.IsNull(thinkingParams.BudgetTokens); + } + + [TestMethod] + public void ChatClientHelper_MapsAdaptiveThinkingCorrectly() + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + }.WithAdaptiveThinking(ThinkingEffort.medium); + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert + Assert.IsNotNull(messageParams.Thinking); + Assert.AreEqual(ThinkingType.adaptive, messageParams.Thinking.Type); + Assert.IsNull(messageParams.Thinking.BudgetTokens); + Assert.IsNotNull(messageParams.OutputConfig); + Assert.AreEqual(ThinkingEffort.medium, messageParams.OutputConfig.Effort); + } + + [TestMethod] + public void ChatClientHelper_MapsAdaptiveThinkingWithoutEffort() + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + }.WithAdaptiveThinking(); + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert + Assert.IsNotNull(messageParams.Thinking); + Assert.AreEqual(ThinkingType.adaptive, messageParams.Thinking.Type); + Assert.IsNull(messageParams.Thinking.BudgetTokens); + Assert.IsNull(messageParams.OutputConfig); + } + + [TestMethod] + public void ChatClientHelper_MapsReasoningOptionsToAdaptiveThinking() + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + Reasoning = new ReasoningOptions { Effort = ReasoningEffort.Medium } + }; + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert + Assert.IsNotNull(messageParams.Thinking); + Assert.AreEqual(ThinkingType.adaptive, messageParams.Thinking.Type); + Assert.IsNull(messageParams.Thinking.BudgetTokens); + Assert.IsNotNull(messageParams.OutputConfig); + Assert.AreEqual(ThinkingEffort.medium, messageParams.OutputConfig.Effort); + } + + [TestMethod] + [DataRow(ReasoningEffort.Low, ThinkingEffort.low)] + [DataRow(ReasoningEffort.Medium, ThinkingEffort.medium)] + [DataRow(ReasoningEffort.High, ThinkingEffort.high)] + [DataRow(ReasoningEffort.ExtraHigh, ThinkingEffort.max)] + public void ChatClientHelper_MapsAllReasoningEffortLevels(ReasoningEffort reasoningEffort, ThinkingEffort expectedEffort) + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + Reasoning = new ReasoningOptions { Effort = reasoningEffort } + }; + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert + Assert.IsNotNull(messageParams.Thinking); + Assert.AreEqual(ThinkingType.adaptive, messageParams.Thinking.Type); + Assert.IsNotNull(messageParams.OutputConfig); + Assert.AreEqual(expectedEffort, messageParams.OutputConfig.Effort); + } + + [TestMethod] + public void ChatClientHelper_ReasoningOptionsNone_ClearsThinking() + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + Reasoning = new ReasoningOptions { Effort = ReasoningEffort.None } + }; + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert + Assert.IsNull(messageParams.Thinking); + } + + [TestMethod] + public void ChatClientHelper_ExplicitThinkingTakesPrecedenceOverReasoningOptions() + { + // Arrange + var client = new AnthropicClient().Messages; + var messages = new List + { + new ChatMessage(ChatRole.User, "Test message") + }; + var options = new ChatOptions + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 16000, + Reasoning = new ReasoningOptions { Effort = ReasoningEffort.Low } + }.WithAdaptiveThinking(ThinkingEffort.max); + + // Act + var messageParams = ChatClientHelper.CreateMessageParameters(client, messages, options); + + // Assert - WithAdaptiveThinking should win over ReasoningOptions + Assert.IsNotNull(messageParams.Thinking); + Assert.AreEqual(ThinkingType.adaptive, messageParams.Thinking.Type); + Assert.IsNotNull(messageParams.OutputConfig); + Assert.AreEqual(ThinkingEffort.max, messageParams.OutputConfig.Effort); + } } } \ No newline at end of file diff --git a/Anthropic.SDK.Tests/Messages.ChatClient.cs b/Anthropic.SDK.Tests/Messages.ChatClient.cs index 90ac50c..1f124fb 100644 --- a/Anthropic.SDK.Tests/Messages.ChatClient.cs +++ b/Anthropic.SDK.Tests/Messages.ChatClient.cs @@ -104,6 +104,56 @@ public async Task TestNonStreamingThinkingWithExtensionMethods() Assert.IsTrue(res.Text?.Contains("10") is true, res.Text); } + [TestMethod] + public async Task TestNonStreamingThinkingAdaptiveWithExtensionMethods() + { + IChatClient client = new AnthropicClient().Messages; + + List messages = new() + { + new ChatMessage(ChatRole.User, "How many r's are in the word strawberry?") + }; + + ChatOptions options = new ChatOptions() + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 20000, + Temperature = 1.0f, + }.WithAdaptiveThinking(ThinkingEffort.high); + + var res = await client.GetResponseAsync(messages, options); + Assert.IsTrue(res.Text.Contains("3") is true, res.Text); + messages.AddMessages(res); + messages.Add(new ChatMessage(ChatRole.User, "and how many letters total?")); + res = await client.GetResponseAsync(messages, options); + Assert.IsTrue(res.Text?.Contains("10") is true, res.Text); + } + + [TestMethod] + public async Task TestNonStreamingThinkingAdaptive() + { + IChatClient client = new AnthropicClient().Messages; + + List messages = new() + { + new ChatMessage(ChatRole.User, "How many r's are in the word strawberry?") + }; + + ChatOptions options = new ChatOptions() + { + ModelId = AnthropicModels.Claude46Sonnet, + MaxOutputTokens = 20000, + Temperature = 1.0f, + Reasoning = new ReasoningOptions() + { + Effort = ReasoningEffort.High, + } + }; + + var res = await client.GetResponseAsync(messages, options); + Assert.IsTrue(res.Text.Contains("3") is true, res.Text); + } + [TestMethod] public async Task TestThinkingStreamingWithExtensionMethods() { diff --git a/Anthropic.SDK.Tests/ThinkingModeTests.cs b/Anthropic.SDK.Tests/ThinkingModeTests.cs index 5cbfbf3..81429ab 100644 --- a/Anthropic.SDK.Tests/ThinkingModeTests.cs +++ b/Anthropic.SDK.Tests/ThinkingModeTests.cs @@ -43,6 +43,34 @@ public async Task TestBasicClaude37ThinkingMessage() Assert.IsNotNull(response); } + [TestMethod] + public async Task TestBasicClaude46ThinkingMessage() + { + var client = new AnthropicClient(); + var messages = new List(); + messages.Add(new Message(RoleType.User, "How many r's are in the word strawberry?")); + var parameters = new MessageParameters() + { + Messages = messages, + MaxTokens = 20000, + Model = AnthropicModels.Claude46Sonnet, + Stream = false, + Temperature = 1.0m, + Thinking = new ThinkingParameters() + { + UseInterleavedThinking = true, + Type = ThinkingType.adaptive, + Effort = ThinkingEffort.high, + } + }; + var res = await client.Messages.GetClaudeMessageAsync(parameters); + Assert.IsTrue(res.Content.OfType().Any()); + var response = res.Message.ToString(); + var thoughts = res.Message.ThinkingContent; + Assert.IsNotNull(thoughts); + Assert.IsNotNull(response); + } + [TestMethod] public async Task TestRedactedClaude37ThinkingMessage() { diff --git a/Anthropic.SDK/Anthropic.SDK.csproj b/Anthropic.SDK/Anthropic.SDK.csproj index bbdd8e0..57d22c9 100644 --- a/Anthropic.SDK/Anthropic.SDK.csproj +++ b/Anthropic.SDK/Anthropic.SDK.csproj @@ -36,13 +36,13 @@ - - + + - + diff --git a/Anthropic.SDK/BaseEndpoint.cs b/Anthropic.SDK/BaseEndpoint.cs index d291283..1ae4068 100644 --- a/Anthropic.SDK/BaseEndpoint.cs +++ b/Anthropic.SDK/BaseEndpoint.cs @@ -184,7 +184,10 @@ protected async Task HttpRequestRaw(string url = null, Http DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, Converters = { ContentConverter.Instance }, // Ensure proper Unicode handling for all characters - Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), +#if DEBUG + WriteIndented = true, +#endif }; string jsonContent = JsonSerializer.Serialize(postData, options); req.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json"); diff --git a/Anthropic.SDK/Constants/AnthropicModels.cs b/Anthropic.SDK/Constants/AnthropicModels.cs index d104565..f3ae820 100644 --- a/Anthropic.SDK/Constants/AnthropicModels.cs +++ b/Anthropic.SDK/Constants/AnthropicModels.cs @@ -9,6 +9,16 @@ namespace Anthropic.SDK.Constants /// public static class AnthropicModels { + /// + /// Claude 4.6 Opus + /// + public const string Claude46Opus = "claude-opus-4-6"; + + /// + /// Claude 4.6 Opus + /// + public const string Claude46Sonnet = "claude-sonnet-4-6"; + /// /// Claude 4.5 Opus /// diff --git a/Anthropic.SDK/Constants/VertexAIModels.cs b/Anthropic.SDK/Constants/VertexAIModels.cs index 51ebcbc..a79bd61 100644 --- a/Anthropic.SDK/Constants/VertexAIModels.cs +++ b/Anthropic.SDK/Constants/VertexAIModels.cs @@ -46,5 +46,15 @@ public static class VertexAIModels /// Claude 4.5 Opus on Vertex AI /// public const string Claude45Opus = "claude-opus-4-5@20251101"; + + /// + /// Claude 4.6 Sonnet on Vertex AI + /// + public const string Claude46Sonnet = "claude-sonnet-4-6"; + + /// + /// Claude 4.6 Opus on Vertex AI + /// + public const string Claude46Opus = "claude-opus-4-6"; } } diff --git a/Anthropic.SDK/Extensions/ChatOptionsExtensions.cs b/Anthropic.SDK/Extensions/ChatOptionsExtensions.cs index 8f2849c..f0dd699 100644 --- a/Anthropic.SDK/Extensions/ChatOptionsExtensions.cs +++ b/Anthropic.SDK/Extensions/ChatOptionsExtensions.cs @@ -100,6 +100,46 @@ public static ChatOptions WithInterleavedThinking(this ChatOptions options, Thin return options; } + /// + /// Sets adaptive thinking mode, which lets Claude dynamically determine when and how much to use extended thinking. + /// Recommended for Claude Opus 4.6 and Sonnet 4.6. Interleaved thinking is automatically enabled. + /// + /// The ChatOptions instance + /// The ChatOptions instance for fluent chaining + public static ChatOptions WithAdaptiveThinking(this ChatOptions options) + { + if (options == null) + throw new ArgumentNullException(nameof(options)); + + (options.AdditionalProperties ??= new())[ThinkingParametersKey] = new ThinkingParameters + { + Type = ThinkingType.adaptive + }; + + return options; + } + + /// + /// Sets adaptive thinking mode with a specific effort level. The effort level is mapped to output_config.effort + /// to guide how much thinking Claude does. Recommended for Claude Opus 4.6 and Sonnet 4.6. + /// + /// The ChatOptions instance + /// The effort level (low, medium, high, or max) to guide thinking allocation + /// The ChatOptions instance for fluent chaining + public static ChatOptions WithAdaptiveThinking(this ChatOptions options, ThinkingEffort effort) + { + if (options == null) + throw new ArgumentNullException(nameof(options)); + + (options.AdditionalProperties ??= new())[ThinkingParametersKey] = new ThinkingParameters + { + Type = ThinkingType.adaptive, + Effort = effort + }; + + return options; + } + /// /// Gets the thinking parameters from ChatOptions /// diff --git a/Anthropic.SDK/Messaging/ChatClientHelper.cs b/Anthropic.SDK/Messaging/ChatClientHelper.cs index ed6bab9..09f980f 100644 --- a/Anthropic.SDK/Messaging/ChatClientHelper.cs +++ b/Anthropic.SDK/Messaging/ChatClientHelper.cs @@ -143,6 +143,37 @@ public static MessageParameters CreateMessageParameters(IChatClient client, IEnu if (thinkingParameters != null) { parameters.Thinking = thinkingParameters; + + if (thinkingParameters.Effort is { } effort) + { + (parameters.OutputConfig ??= new OutputConfig()).Effort = effort; + } + } + + // Map MEAI ReasoningOptions when the Anthropic-specific extension wasn't used + if (options.Reasoning is { } reasoning && thinkingParameters == null) + { + if (reasoning.Effort is { } reasoningEffort && reasoningEffort != ReasoningEffort.None) + { + parameters.Thinking = new ThinkingParameters + { + Type = ThinkingType.adaptive + }; + + var mapped = reasoningEffort switch + { + ReasoningEffort.Low => ThinkingEffort.low, + ReasoningEffort.Medium => ThinkingEffort.medium, + ReasoningEffort.High => ThinkingEffort.high, + ReasoningEffort.ExtraHigh => ThinkingEffort.max, + _ => (ThinkingEffort?)null + }; + + if (mapped is not null) + { + (parameters.OutputConfig ??= new OutputConfig()).Effort = mapped; + } + } } // Map response format from ChatOptions for structured JSON output diff --git a/Anthropic.SDK/Messaging/MessageParameters.cs b/Anthropic.SDK/Messaging/MessageParameters.cs index 76e3108..e22c72d 100644 --- a/Anthropic.SDK/Messaging/MessageParameters.cs +++ b/Anthropic.SDK/Messaging/MessageParameters.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; @@ -45,10 +46,27 @@ public class MessageParameters : MessageCountTokenParameters /// /// Output format configuration for structured JSON output. - /// Requires the structured-outputs-2025-11-13 beta header. + /// Obsolete and will be removed in the future. /// - [JsonPropertyName("output_format")] - public OutputFormat OutputFormat { get; set; } + [Obsolete] + [JsonIgnore] + public OutputFormat OutputFormat + { + get + { + return OutputConfig?.OutputFormat; + } + set + { + if (OutputConfig == null) + OutputConfig = new OutputConfig(); + + OutputConfig.OutputFormat = value; + } + } + + [JsonPropertyName("output_config")] + public OutputConfig OutputConfig { get; set; } [JsonPropertyName("mcp_servers")] public List MCPServers { get; set; } diff --git a/Anthropic.SDK/Messaging/OutputConfig.cs b/Anthropic.SDK/Messaging/OutputConfig.cs new file mode 100644 index 0000000..e372e06 --- /dev/null +++ b/Anthropic.SDK/Messaging/OutputConfig.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Anthropic.SDK.Messaging +{ + public class OutputConfig + { + [JsonPropertyName("effort")] + public ThinkingEffort? Effort { get; set; } + + [JsonPropertyName("format")] + public OutputFormat OutputFormat { get; set; } + } +} diff --git a/Anthropic.SDK/Messaging/ThinkingEffort.cs b/Anthropic.SDK/Messaging/ThinkingEffort.cs new file mode 100644 index 0000000..1e7c157 --- /dev/null +++ b/Anthropic.SDK/Messaging/ThinkingEffort.cs @@ -0,0 +1,13 @@ +using System; +using System.Text.Json.Serialization; + +namespace Anthropic.SDK.Messaging; + +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ThinkingEffort +{ + low, + medium, + high, + max +} \ No newline at end of file diff --git a/Anthropic.SDK/Messaging/ThinkingParameters.cs b/Anthropic.SDK/Messaging/ThinkingParameters.cs index da334ab..f246832 100644 --- a/Anthropic.SDK/Messaging/ThinkingParameters.cs +++ b/Anthropic.SDK/Messaging/ThinkingParameters.cs @@ -1,22 +1,30 @@ -using System; +using System; using System.Collections.Generic; using System.Text; using System.Text.Json.Serialization; namespace Anthropic.SDK.Messaging { - + public class ThinkingParameters { [JsonPropertyName("type")] - public string Type => "enabled"; + public ThinkingType Type { get; set; } = ThinkingType.enabled; + [JsonPropertyName("budget_tokens")] - public int BudgetTokens { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? BudgetTokens { get; set; } /// /// Indicates whether to use interleaved thinking mode which allows thinking tokens to exceed max_tokens /// [JsonIgnore] public bool UseInterleavedThinking { get; set; } + + /// + /// The effort level to map to output_config.effort when using adaptive thinking + /// + [JsonIgnore] + public ThinkingEffort? Effort { get; set; } } } diff --git a/Anthropic.SDK/Messaging/ThinkingType.cs b/Anthropic.SDK/Messaging/ThinkingType.cs new file mode 100644 index 0000000..2e49569 --- /dev/null +++ b/Anthropic.SDK/Messaging/ThinkingType.cs @@ -0,0 +1,12 @@ +using System; +using System.Text.Json.Serialization; + +namespace Anthropic.SDK.Messaging; + +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ThinkingType +{ + enabled, + + adaptive +} \ No newline at end of file diff --git a/Anthropic.SDK/Messaging/VertexAIMessagesEndpoint.cs b/Anthropic.SDK/Messaging/VertexAIMessagesEndpoint.cs index fc12afe..3a34bfb 100644 --- a/Anthropic.SDK/Messaging/VertexAIMessagesEndpoint.cs +++ b/Anthropic.SDK/Messaging/VertexAIMessagesEndpoint.cs @@ -325,7 +325,8 @@ private object CreateVertexAIRequest(MessageParameters parameters) stream = parameters.Stream, tools = parameters.Tools?.Select(t => t.Function).ToList(), tool_choice = parameters.ToolChoice, - thinking = parameters.Thinking + thinking = parameters.Thinking, + output_config = parameters.OutputConfig // Note: We don't need to include model here as it's part of the URL for Vertex AI };