From 18d50684407e6d1cf4895273d19a8054231f65ef Mon Sep 17 00:00:00 2001 From: Jacob Alber Date: Mon, 2 Dec 2024 16:56:42 -0500 Subject: [PATCH] refactor: Replatform AutoGen.Anthropic project on M.AG.Extensions.Anthropic * Keep public types in same namespaces for now * Forward types to enable drop-in replacement --- .../Agent/AnthropicClientAgent.cs | 1 + .../src/AutoGen.Anthropic/AnthropicClient.cs | 203 ------------------ .../AutoGen.Anthropic.csproj | 1 + .../Converters/ContentBaseConverter.cs | 39 ---- .../JsonPropertyNameEnumCoverter.cs | 44 ---- .../Converters/SystemMessageConverter.cs | 42 ---- .../DTO/ChatCompletionRequest.cs | 94 -------- .../DTO/ChatCompletionResponse.cs | 96 --------- dotnet/src/AutoGen.Anthropic/DTO/Content.cs | 95 -------- .../AutoGen.Anthropic/DTO/ErrorResponse.cs | 21 -- dotnet/src/AutoGen.Anthropic/DTO/Tool.cs | 43 ---- .../src/AutoGen.Anthropic/DTO/ToolChoice.cs | 39 ---- .../src/AutoGen.Anthropic/TypeForwarding.cs | 32 +++ .../Utils/AnthropicConstants.cs | 15 -- .../AnthropicChatCompletionClient.cs | 20 +- .../Extensions/Anthropic/AnthropicClient.cs | 6 +- .../Converters/ContentBaseConverter.cs | 4 +- .../JsonPropertyNameEnumCoverter.cs | 2 +- .../Converters/SystemMessageConverter.cs | 2 +- .../Anthropic/DTO/ChatCompletionRequest.cs | 2 +- .../Anthropic/DTO/ChatCompletionResponse.cs | 2 +- .../Extensions/Anthropic/DTO/Content.cs | 4 +- .../Extensions/Anthropic/DTO/ErrorResponse.cs | 2 +- .../Extensions/Anthropic/DTO/Tool.cs | 4 +- .../Extensions/Anthropic/DTO/ToolChoice.cs | 4 +- ...rosoft.AutoGen.Extensions.Anthropic.csproj | 4 +- .../Anthropic/Utils/AnthropicConstants.cs | 31 ++- .../AnthropicClientAgentTest.cs | 2 + .../AnthropicClientTest.cs | 8 +- .../AnthropicTestFunctionCalls.cs | 2 +- .../AnthropicTestUtils.cs | 2 +- .../AutoGen.Anthropic.Tests.csproj | 1 + 32 files changed, 99 insertions(+), 768 deletions(-) delete mode 100644 dotnet/src/AutoGen.Anthropic/AnthropicClient.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/Converters/ContentBaseConverter.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/Converters/JsonPropertyNameEnumCoverter.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/Converters/SystemMessageConverter.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionRequest.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionResponse.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/Content.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/ErrorResponse.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/Tool.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/DTO/ToolChoice.cs create mode 100644 dotnet/src/AutoGen.Anthropic/TypeForwarding.cs delete mode 100644 dotnet/src/AutoGen.Anthropic/Utils/AnthropicConstants.cs diff --git a/dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs b/dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs index 6abc2786b0ff..114bd8c93a4f 100644 --- a/dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs +++ b/dotnet/src/AutoGen.Anthropic/Agent/AnthropicClientAgent.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using AutoGen.Anthropic.DTO; + using AutoGen.Core; namespace AutoGen.Anthropic; diff --git a/dotnet/src/AutoGen.Anthropic/AnthropicClient.cs b/dotnet/src/AutoGen.Anthropic/AnthropicClient.cs deleted file mode 100644 index f940864cec1c..000000000000 --- a/dotnet/src/AutoGen.Anthropic/AnthropicClient.cs +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// AnthropicClient.cs - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Runtime.CompilerServices; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; -using AutoGen.Anthropic.Converters; -using AutoGen.Anthropic.DTO; - -namespace AutoGen.Anthropic; - -public sealed class AnthropicClient : IDisposable -{ - private readonly HttpClient _httpClient; - private readonly string _baseUrl; - - private static readonly JsonSerializerOptions JsonSerializerOptions = new() - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - Converters = - { - new ContentBaseConverter(), - new JsonPropertyNameEnumConverter(), - new JsonPropertyNameEnumConverter(), - new SystemMessageConverter(), - } - }; - - public AnthropicClient(HttpClient httpClient, string baseUrl, string apiKey) - { - _httpClient = httpClient; - _baseUrl = baseUrl; - - _httpClient.DefaultRequestHeaders.Add("x-api-key", apiKey); - _httpClient.DefaultRequestHeaders.Add("anthropic-version", "2023-06-01"); - } - - public async Task CreateChatCompletionsAsync(ChatCompletionRequest chatCompletionRequest, - CancellationToken cancellationToken) - { - var httpResponseMessage = await SendRequestAsync(chatCompletionRequest, cancellationToken); - var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync(); - - if (httpResponseMessage.IsSuccessStatusCode) - { - return await DeserializeResponseAsync(responseStream, cancellationToken); - } - - ErrorResponse res = await DeserializeResponseAsync(responseStream, cancellationToken); - throw new Exception(res.Error?.Message); - } - - public async IAsyncEnumerable StreamingChatCompletionsAsync( - ChatCompletionRequest chatCompletionRequest, [EnumeratorCancellation] CancellationToken cancellationToken) - { - var httpResponseMessage = await SendRequestAsync(chatCompletionRequest, cancellationToken); - using var reader = new StreamReader(await httpResponseMessage.Content.ReadAsStreamAsync()); - - var currentEvent = new SseEvent(); - - while (await reader.ReadLineAsync() is { } line) - { - if (!string.IsNullOrEmpty(line)) - { - if (line.StartsWith("event:")) - { - currentEvent.EventType = line.Substring("event:".Length).Trim(); - } - else if (line.StartsWith("data:")) - { - currentEvent.Data = line.Substring("data:".Length).Trim(); - } - } - else // an empty line indicates the end of an event - { - if (currentEvent.EventType == "content_block_start" && !string.IsNullOrEmpty(currentEvent.Data)) - { - var dataBlock = JsonSerializer.Deserialize(currentEvent.Data!); - if (dataBlock != null && dataBlock.ContentBlock?.Type == "tool_use") - { - currentEvent.ContentBlock = dataBlock.ContentBlock; - } - } - - if (currentEvent.EventType is "message_start" or "content_block_delta" or "message_delta" && currentEvent.Data != null) - { - var res = await JsonSerializer.DeserializeAsync( - new MemoryStream(Encoding.UTF8.GetBytes(currentEvent.Data)), - cancellationToken: cancellationToken) ?? throw new Exception("Failed to deserialize response"); - if (res.Delta?.Type == "input_json_delta" && !string.IsNullOrEmpty(res.Delta.PartialJson) && - currentEvent.ContentBlock != null) - { - currentEvent.ContentBlock.AppendDeltaParameters(res.Delta.PartialJson!); - } - else if (res.Delta is { StopReason: "tool_use" } && currentEvent.ContentBlock != null) - { - if (res.Content == null) - { - res.Content = [currentEvent.ContentBlock.CreateToolUseContent()]; - } - else - { - res.Content.Add(currentEvent.ContentBlock.CreateToolUseContent()); - } - - currentEvent = new SseEvent(); - } - - yield return res; - } - else if (currentEvent.EventType == "error" && currentEvent.Data != null) - { - var res = await JsonSerializer.DeserializeAsync( - new MemoryStream(Encoding.UTF8.GetBytes(currentEvent.Data)), cancellationToken: cancellationToken); - - throw new Exception(res?.Error?.Message); - } - - if (currentEvent.ContentBlock == null) - { - currentEvent = new SseEvent(); - } - } - } - } - - private Task SendRequestAsync(T requestObject, CancellationToken cancellationToken) - { - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, _baseUrl); - var jsonRequest = JsonSerializer.Serialize(requestObject, JsonSerializerOptions); - httpRequestMessage.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); - httpRequestMessage.Headers.Add("anthropic-beta", "prompt-caching-2024-07-31"); - return _httpClient.SendAsync(httpRequestMessage, cancellationToken); - } - - private async Task DeserializeResponseAsync(Stream responseStream, CancellationToken cancellationToken) - { - return await JsonSerializer.DeserializeAsync(responseStream, JsonSerializerOptions, cancellationToken) - ?? throw new Exception("Failed to deserialize response"); - } - - public void Dispose() - { - _httpClient.Dispose(); - } - - private struct SseEvent - { - public string EventType { get; set; } - public string? Data { get; set; } - public ContentBlock? ContentBlock { get; set; } - - public SseEvent(string eventType, string? data = null, ContentBlock? contentBlock = null) - { - EventType = eventType; - Data = data; - ContentBlock = contentBlock; - } - } - - private sealed class ContentBlock - { - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("id")] - public string? Id { get; set; } - - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("input")] - public object? Input { get; set; } - - [JsonPropertyName("parameters")] - public string? Parameters { get; set; } - - public void AppendDeltaParameters(string deltaParams) - { - StringBuilder sb = new StringBuilder(Parameters); - sb.Append(deltaParams); - Parameters = sb.ToString(); - } - - public ToolUseContent CreateToolUseContent() - { - return new ToolUseContent { Id = Id, Name = Name, Input = Parameters }; - } - } - - private sealed class DataBlock - { - [JsonPropertyName("content_block")] - public ContentBlock? ContentBlock { get; set; } - } -} diff --git a/dotnet/src/AutoGen.Anthropic/AutoGen.Anthropic.csproj b/dotnet/src/AutoGen.Anthropic/AutoGen.Anthropic.csproj index a4fd32e7e345..dab9b978e163 100644 --- a/dotnet/src/AutoGen.Anthropic/AutoGen.Anthropic.csproj +++ b/dotnet/src/AutoGen.Anthropic/AutoGen.Anthropic.csproj @@ -17,6 +17,7 @@ + diff --git a/dotnet/src/AutoGen.Anthropic/Converters/ContentBaseConverter.cs b/dotnet/src/AutoGen.Anthropic/Converters/ContentBaseConverter.cs deleted file mode 100644 index 76c3200c1165..000000000000 --- a/dotnet/src/AutoGen.Anthropic/Converters/ContentBaseConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ContentBaseConverter.cs - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; -using AutoGen.Anthropic.DTO; -namespace AutoGen.Anthropic.Converters; - -public sealed class ContentBaseConverter : JsonConverter -{ - public override ContentBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - using var doc = JsonDocument.ParseValue(ref reader); - if (doc.RootElement.TryGetProperty("type", out JsonElement typeProperty) && !string.IsNullOrEmpty(typeProperty.GetString())) - { - string? type = typeProperty.GetString(); - var text = doc.RootElement.GetRawText(); - switch (type) - { - case "text": - return JsonSerializer.Deserialize(text, options) ?? throw new InvalidOperationException(); - case "image": - return JsonSerializer.Deserialize(text, options) ?? throw new InvalidOperationException(); - case "tool_use": - return JsonSerializer.Deserialize(text, options) ?? throw new InvalidOperationException(); - case "tool_result": - return JsonSerializer.Deserialize(text, options) ?? throw new InvalidOperationException(); - } - } - - throw new JsonException("Unknown content type"); - } - - public override void Write(Utf8JsonWriter writer, ContentBase value, JsonSerializerOptions options) - { - JsonSerializer.Serialize(writer, value, value.GetType(), options); - } -} diff --git a/dotnet/src/AutoGen.Anthropic/Converters/JsonPropertyNameEnumCoverter.cs b/dotnet/src/AutoGen.Anthropic/Converters/JsonPropertyNameEnumCoverter.cs deleted file mode 100644 index 44ceb0718f3a..000000000000 --- a/dotnet/src/AutoGen.Anthropic/Converters/JsonPropertyNameEnumCoverter.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// JsonPropertyNameEnumCoverter.cs - -using System; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace AutoGen.Anthropic.Converters; - -internal sealed class JsonPropertyNameEnumConverter : JsonConverter where T : struct, Enum -{ - public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - string value = reader.GetString() ?? throw new JsonException("Value was null."); - - foreach (var field in typeToConvert.GetFields()) - { - var attribute = field.GetCustomAttribute(); - if (attribute?.Name == value) - { - return (T)Enum.Parse(typeToConvert, field.Name); - } - } - - throw new JsonException($"Unable to convert \"{value}\" to enum {typeToConvert}."); - } - - public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) - { - var field = value.GetType().GetField(value.ToString()); - var attribute = field?.GetCustomAttribute(); - - if (attribute != null) - { - writer.WriteStringValue(attribute.Name); - } - else - { - writer.WriteStringValue(value.ToString()); - } - } -} - diff --git a/dotnet/src/AutoGen.Anthropic/Converters/SystemMessageConverter.cs b/dotnet/src/AutoGen.Anthropic/Converters/SystemMessageConverter.cs deleted file mode 100644 index 0af3fa1a9059..000000000000 --- a/dotnet/src/AutoGen.Anthropic/Converters/SystemMessageConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// SystemMessageConverter.cs - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; -using AutoGen.Anthropic.DTO; - -namespace AutoGen.Anthropic.Converters; - -public class SystemMessageConverter : JsonConverter -{ - public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - return reader.GetString() ?? string.Empty; - } - if (reader.TokenType == JsonTokenType.StartArray) - { - return JsonSerializer.Deserialize(ref reader, options) ?? throw new InvalidOperationException(); - } - - throw new JsonException(); - } - - public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) - { - if (value is string stringValue) - { - writer.WriteStringValue(stringValue); - } - else if (value is SystemMessage[] arrayValue) - { - JsonSerializer.Serialize(writer, arrayValue, options); - } - else - { - throw new JsonException(); - } - } -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionRequest.cs b/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionRequest.cs deleted file mode 100644 index c3f378dffe3a..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionRequest.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ChatCompletionRequest.cs - -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace AutoGen.Anthropic.DTO; - -public class ChatCompletionRequest -{ - [JsonPropertyName("model")] - public string? Model { get; set; } - - [JsonPropertyName("messages")] - public List Messages { get; set; } - - [JsonPropertyName("system")] - public SystemMessage[]? SystemMessage { get; set; } - - [JsonPropertyName("max_tokens")] - public int MaxTokens { get; set; } - - [JsonPropertyName("metadata")] - public object? Metadata { get; set; } - - [JsonPropertyName("stop_sequences")] - public string[]? StopSequences { get; set; } - - [JsonPropertyName("stream")] - public bool? Stream { get; set; } - - [JsonPropertyName("temperature")] - public decimal? Temperature { get; set; } - - [JsonPropertyName("top_k")] - public int? TopK { get; set; } - - [JsonPropertyName("top_p")] - public decimal? TopP { get; set; } - - [JsonPropertyName("tools")] - public List? Tools { get; set; } - - [JsonPropertyName("tool_choice")] - public ToolChoice? ToolChoice { get; set; } - - public ChatCompletionRequest() - { - Messages = new List(); - } -} - -public class SystemMessage -{ - [JsonPropertyName("text")] - public string? Text { get; set; } - - [JsonPropertyName("type")] - public string? Type { get; private set; } = "text"; - - [JsonPropertyName("cache_control")] - public CacheControl? CacheControl { get; set; } - - public static SystemMessage CreateSystemMessage(string systemMessage) => new() { Text = systemMessage }; - - public static SystemMessage CreateSystemMessageWithCacheControl(string systemMessage) => new() - { - Text = systemMessage, - CacheControl = new CacheControl { Type = CacheControlType.Ephemeral } - }; -} - -public class ChatMessage -{ - [JsonPropertyName("role")] - public string Role { get; set; } - - [JsonPropertyName("content")] - public List Content { get; set; } - - public ChatMessage(string role, string content) - { - Role = role; - Content = new List() { new TextContent { Text = content } }; - } - - public ChatMessage(string role, List content) - { - Role = role; - Content = content; - } - - public void AddContent(ContentBase content) => Content.Add(content); -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionResponse.cs b/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionResponse.cs deleted file mode 100644 index 3b0135d38eb1..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/ChatCompletionResponse.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ChatCompletionResponse.cs - -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace AutoGen.Anthropic.DTO; -public class ChatCompletionResponse -{ - [JsonPropertyName("content")] - public List? Content { get; set; } - - [JsonPropertyName("id")] - public string? Id { get; set; } - - [JsonPropertyName("model")] - public string? Model { get; set; } - - [JsonPropertyName("role")] - public string? Role { get; set; } - - [JsonPropertyName("stop_reason")] - public string? StopReason { get; set; } - - [JsonPropertyName("stop_sequence")] - public object? StopSequence { get; set; } - - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("usage")] - public Usage? Usage { get; set; } - - [JsonPropertyName("delta")] - public Delta? Delta { get; set; } - - [JsonPropertyName("message")] - public StreamingMessage? StreamingMessage { get; set; } -} - -public class StreamingMessage -{ - [JsonPropertyName("id")] - public string? Id { get; set; } - - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("role")] - public string? Role { get; set; } - - [JsonPropertyName("model")] - public string? Model { get; set; } - - [JsonPropertyName("stop_reason")] - public object? StopReason { get; set; } - - [JsonPropertyName("stop_sequence")] - public object? StopSequence { get; set; } - - [JsonPropertyName("usage")] - public Usage? Usage { get; set; } -} - -public class Usage -{ - [JsonPropertyName("input_tokens")] - public int InputTokens { get; set; } - - [JsonPropertyName("output_tokens")] - public int OutputTokens { get; set; } - - [JsonPropertyName("cache_creation_input_tokens")] - public int CacheCreationInputTokens { get; set; } - - [JsonPropertyName("cache_read_input_tokens")] - public int CacheReadInputTokens { get; set; } -} - -public class Delta -{ - [JsonPropertyName("stop_reason")] - public string? StopReason { get; set; } - - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("text")] - public string? Text { get; set; } - - [JsonPropertyName("partial_json")] - public string? PartialJson { get; set; } - - [JsonPropertyName("usage")] - public Usage? Usage { get; set; } -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/Content.cs b/dotnet/src/AutoGen.Anthropic/DTO/Content.cs deleted file mode 100644 index 8256aacbc678..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/Content.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Content.cs - -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using AutoGen.Anthropic.Converters; - -namespace AutoGen.Anthropic.DTO; - -public abstract class ContentBase -{ - [JsonPropertyName("type")] - public abstract string Type { get; } - - [JsonPropertyName("cache_control")] - public CacheControl? CacheControl { get; set; } -} - -public class TextContent : ContentBase -{ - [JsonPropertyName("type")] - public override string Type => "text"; - - [JsonPropertyName("text")] - public string? Text { get; set; } - - public static TextContent CreateTextWithCacheControl(string text) => new() - { - Text = text, - CacheControl = new CacheControl { Type = CacheControlType.Ephemeral } - }; -} - -public class ImageContent : ContentBase -{ - [JsonPropertyName("type")] - public override string Type => "image"; - - [JsonPropertyName("source")] - public ImageSource? Source { get; set; } -} - -public class ImageSource -{ - [JsonPropertyName("type")] - public string Type => "base64"; - - [JsonPropertyName("media_type")] - public string? MediaType { get; set; } - - [JsonPropertyName("data")] - public string? Data { get; set; } -} - -public class ToolUseContent : ContentBase -{ - [JsonPropertyName("type")] - public override string Type => "tool_use"; - - [JsonPropertyName("id")] - public string? Id { get; set; } - - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("input")] - public JsonNode? Input { get; set; } -} - -public class ToolResultContent : ContentBase -{ - [JsonPropertyName("type")] - public override string Type => "tool_result"; - - [JsonPropertyName("tool_use_id")] - public string? Id { get; set; } - - [JsonPropertyName("content")] - public string? Content { get; set; } -} - -public class CacheControl -{ - [JsonPropertyName("type")] - public CacheControlType Type { get; set; } - - public static CacheControl Create() => new CacheControl { Type = CacheControlType.Ephemeral }; -} - -[JsonConverter(typeof(JsonPropertyNameEnumConverter))] -public enum CacheControlType -{ - [JsonPropertyName("ephemeral")] - Ephemeral -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/ErrorResponse.cs b/dotnet/src/AutoGen.Anthropic/DTO/ErrorResponse.cs deleted file mode 100644 index d02a8f6d1cfc..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/ErrorResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ErrorResponse.cs - -using System.Text.Json.Serialization; - -namespace AutoGen.Anthropic.DTO; - -public sealed class ErrorResponse -{ - [JsonPropertyName("error")] - public Error? Error { get; set; } -} - -public sealed class Error -{ - [JsonPropertyName("Type")] - public string? Type { get; set; } - - [JsonPropertyName("message")] - public string? Message { get; set; } -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/Tool.cs b/dotnet/src/AutoGen.Anthropic/DTO/Tool.cs deleted file mode 100644 index e230899f22a9..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/Tool.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Tool.cs - -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace AutoGen.Anthropic.DTO; - -public class Tool -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("description")] - public string? Description { get; set; } - - [JsonPropertyName("input_schema")] - public InputSchema? InputSchema { get; set; } - - [JsonPropertyName("cache_control")] - public CacheControl? CacheControl { get; set; } -} - -public class InputSchema -{ - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("properties")] - public Dictionary? Properties { get; set; } - - [JsonPropertyName("required")] - public List? Required { get; set; } -} - -public class SchemaProperty -{ - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("description")] - public string? Description { get; set; } -} diff --git a/dotnet/src/AutoGen.Anthropic/DTO/ToolChoice.cs b/dotnet/src/AutoGen.Anthropic/DTO/ToolChoice.cs deleted file mode 100644 index 2cb5463c5318..000000000000 --- a/dotnet/src/AutoGen.Anthropic/DTO/ToolChoice.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ToolChoice.cs - -using System.Text.Json.Serialization; -using AutoGen.Anthropic.Converters; - -namespace AutoGen.Anthropic.DTO; - -[JsonConverter(typeof(JsonPropertyNameEnumConverter))] -public enum ToolChoiceType -{ - [JsonPropertyName("auto")] - Auto, // Default behavior - - [JsonPropertyName("any")] - Any, // Use any provided tool - - [JsonPropertyName("tool")] - Tool // Force a specific tool -} - -public class ToolChoice -{ - [JsonPropertyName("type")] - public ToolChoiceType Type { get; set; } - - [JsonPropertyName("name")] - public string? Name { get; set; } - - private ToolChoice(ToolChoiceType type, string? name = null) - { - Type = type; - Name = name; - } - - public static ToolChoice Auto => new(ToolChoiceType.Auto); - public static ToolChoice Any => new(ToolChoiceType.Any); - public static ToolChoice ToolUse(string name) => new(ToolChoiceType.Tool, name); -} diff --git a/dotnet/src/AutoGen.Anthropic/TypeForwarding.cs b/dotnet/src/AutoGen.Anthropic/TypeForwarding.cs new file mode 100644 index 000000000000..0fea360c92c3 --- /dev/null +++ b/dotnet/src/AutoGen.Anthropic/TypeForwarding.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// TypeForwarding.cs + +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.Converters.ContentBaseConverter))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.Converters.SystemMessageConverter))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.AIContentExtensions))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.CacheControl))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.CacheControlType))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ChatCompletionRequest))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ChatCompletionResponse))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ChatMessage))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ContentBase))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.Delta))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.Error))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ErrorResponse))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ImageContent))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ImageSource))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.InputSchema))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.SchemaProperty))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.StreamingMessage))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.SystemMessage))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.TextContent))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.Tool))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ToolChoice))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ToolChoiceType))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ToolResultContent))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.ToolUseContent))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.DTO.Usage))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.Utils.AnthropicConstants))] +[assembly: TypeForwardedTo(typeof(AutoGen.Anthropic.AnthropicClient))] diff --git a/dotnet/src/AutoGen.Anthropic/Utils/AnthropicConstants.cs b/dotnet/src/AutoGen.Anthropic/Utils/AnthropicConstants.cs deleted file mode 100644 index e445b42ee109..000000000000 --- a/dotnet/src/AutoGen.Anthropic/Utils/AnthropicConstants.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// AnthropicConstants.cs - -namespace AutoGen.Anthropic.Utils; - -public static class AnthropicConstants -{ - public static string Endpoint = "https://api.anthropic.com/v1/messages"; - - // Models - public static string Claude3Opus = "claude-3-opus-20240229"; - public static string Claude3Sonnet = "claude-3-sonnet-20240229"; - public static string Claude3Haiku = "claude-3-haiku-20240307"; - public static string Claude35Sonnet = "claude-3-5-sonnet-20240620"; -} diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicChatCompletionClient.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicChatCompletionClient.cs index 6248bd4462e0..9464874a9e1f 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicChatCompletionClient.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicChatCompletionClient.cs @@ -1,11 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // AnthropicChatCompletionClient.cs -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -using Microsoft.AutoGen.Extensions.Anthropic.DTO; +using AutoGen.Anthropic.DTO; using Microsoft.Extensions.AI; using MEAI = Microsoft.Extensions.AI; +using DTO = AutoGen.Anthropic.DTO; + +using AutoGen.Anthropic; + +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace Microsoft.AutoGen.Extensions.Anthropic; @@ -26,7 +32,11 @@ public AnthropicChatCompletionClient(HttpClient httpClient, string modelId, stri { } - public AnthropicChatCompletionClient([NotNull] AnthropicClient client, string modelId) + public AnthropicChatCompletionClient( +#if NET8_0_OR_GREATER // TODO: Should this be lower? + [NotNull] +#endif + AnthropicClient client, string modelId) { if (client == null) { @@ -54,7 +64,7 @@ private DTO.ChatMessage Translate(MEAI.ChatMessage message, List? if (message.Contents.Count != 1 || message.Text == null) { throw new Exception($"Invalid SystemMessage: May only contain a single Text AIContent. Actual: { - String.Join(',', from contentObject in message.Contents select contentObject.GetType()) + String.Join(",", from contentObject in message.Contents select contentObject.GetType()) }"); } @@ -128,7 +138,7 @@ where abstractTool is AIFunction }; } - private class ChatCompletionAccumulator + private sealed class ChatCompletionAccumulator { public string? CompletionId { get; set; } public string? ModelId { get; set; } diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicClient.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicClient.cs index 07388d6820eb..b5ad91f10d4b 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicClient.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/AnthropicClient.cs @@ -7,10 +7,10 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Microsoft.AutoGen.Extensions.Anthropic.Converters; -using Microsoft.AutoGen.Extensions.Anthropic.DTO; +using AutoGen.Anthropic.Converters; +using AutoGen.Anthropic.DTO; -namespace Microsoft.AutoGen.Extensions.Anthropic; +namespace AutoGen.Anthropic; public sealed class AnthropicClient : IDisposable { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/ContentBaseConverter.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/ContentBaseConverter.cs index 024c0f5fbbe4..9062435243d3 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/ContentBaseConverter.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/ContentBaseConverter.cs @@ -3,9 +3,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Microsoft.AutoGen.Extensions.Anthropic.DTO; +using AutoGen.Anthropic.DTO; -namespace Microsoft.AutoGen.Extensions.Anthropic.Converters; +namespace AutoGen.Anthropic.Converters; public sealed class ContentBaseConverter : JsonConverter { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/JsonPropertyNameEnumCoverter.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/JsonPropertyNameEnumCoverter.cs index f3412643ffc0..fc79f7d123f5 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/JsonPropertyNameEnumCoverter.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/JsonPropertyNameEnumCoverter.cs @@ -5,7 +5,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Microsoft.AutoGen.Extensions.Anthropic.Converters; +namespace AutoGen.Anthropic.Converters; internal sealed class JsonPropertyNameEnumConverter : JsonConverter where T : struct, Enum { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/SystemMessageConverter.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/SystemMessageConverter.cs index 1e7414055d17..97001a43f96d 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/SystemMessageConverter.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Converters/SystemMessageConverter.cs @@ -5,7 +5,7 @@ using System.Text.Json.Serialization; using AutoGen.Anthropic.DTO; -namespace Microsoft.AutoGen.Extensions.Anthropic.Converters; +namespace AutoGen.Anthropic.Converters; public class SystemMessageConverter : JsonConverter { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionRequest.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionRequest.cs index 82ade7def8fa..3fef90a5b2c4 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionRequest.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionRequest.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; public class ChatCompletionRequest { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionResponse.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionResponse.cs index 5ca0212fd692..7b7b2cca417e 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionResponse.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ChatCompletionResponse.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; public class ChatCompletionResponse { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Content.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Content.cs index 6e3403cb2c9f..8f8bd53e84aa 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Content.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Content.cs @@ -4,9 +4,9 @@ using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; -using Microsoft.AutoGen.Extensions.Anthropic.Converters; +using AutoGen.Anthropic.Converters; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; public static class AIContentExtensions { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ErrorResponse.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ErrorResponse.cs index 38dd7411d481..d02a8f6d1cfc 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ErrorResponse.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ErrorResponse.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; public sealed class ErrorResponse { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Tool.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Tool.cs index bd2ca6ba46b5..f47a10f0fa77 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Tool.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/Tool.cs @@ -4,7 +4,7 @@ using System.Text.Json.Serialization; using Microsoft.Extensions.AI; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; public class Tool { @@ -20,8 +20,6 @@ public class Tool [JsonPropertyName("cache_control")] public CacheControl? CacheControl { get; set; } - - // Implicit conversion operator from M.E.AI.AITool to Tool public static implicit operator Tool(Microsoft.Extensions.AI.AIFunction tool) { diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ToolChoice.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ToolChoice.cs index 2ec788a348c6..2cb5463c5318 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ToolChoice.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/DTO/ToolChoice.cs @@ -2,9 +2,9 @@ // ToolChoice.cs using System.Text.Json.Serialization; -using Microsoft.AutoGen.Extensions.Anthropic.Converters; +using AutoGen.Anthropic.Converters; -namespace Microsoft.AutoGen.Extensions.Anthropic.DTO; +namespace AutoGen.Anthropic.DTO; [JsonConverter(typeof(JsonPropertyNameEnumConverter))] public enum ToolChoiceType diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Microsoft.AutoGen.Extensions.Anthropic.csproj b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Microsoft.AutoGen.Extensions.Anthropic.csproj index 846d18f9fca4..4674bb55ad29 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Microsoft.AutoGen.Extensions.Anthropic.csproj +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Microsoft.AutoGen.Extensions.Anthropic.csproj @@ -1,6 +1,6 @@ - net8.0 + $(PackageTargetFrameworks) enable enable @@ -17,7 +17,7 @@ - + diff --git a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Utils/AnthropicConstants.cs b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Utils/AnthropicConstants.cs index 739aa680f9a3..305d2bbe7d81 100644 --- a/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Utils/AnthropicConstants.cs +++ b/dotnet/src/Microsoft.AutoGen/Extensions/Anthropic/Utils/AnthropicConstants.cs @@ -1,15 +1,30 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // AnthropicConstants.cs -namespace Microsoft.AutoGen.Extensions.Anthropic.Utils; +namespace AutoGen.Anthropic.Utils +{ + public static class AnthropicConstants + { + public static string Endpoint = "https://api.anthropic.com/v1/messages"; + + // Models + public static string Claude3Opus = "claude-3-opus-20240229"; + public static string Claude3Sonnet = "claude-3-sonnet-20240229"; + public static string Claude3Haiku = "claude-3-haiku-20240307"; + public static string Claude35Sonnet = "claude-3-5-sonnet-20240620"; + } +} -public static class AnthropicConstants +namespace Microsoft.AutoGen.Extensions.Anthropic.Utils { - public static string Endpoint = "https://api.anthropic.com/v1/messages"; + public static class AnthropicConstants + { + public static string Endpoint = global::AutoGen.Anthropic.Utils.AnthropicConstants.Endpoint; - // Models - public static string Claude3Opus = "claude-3-opus-20240229"; - public static string Claude3Sonnet = "claude-3-sonnet-20240229"; - public static string Claude3Haiku = "claude-3-haiku-20240307"; - public static string Claude35Sonnet = "claude-3-5-sonnet-20240620"; + // Models + public static string Claude3Opus = global::AutoGen.Anthropic.Utils.AnthropicConstants.Claude3Opus; + public static string Claude3Sonnet = global::AutoGen.Anthropic.Utils.AnthropicConstants.Claude3Sonnet; + public static string Claude3Haiku = global::AutoGen.Anthropic.Utils.AnthropicConstants.Claude3Haiku; + public static string Claude35Sonnet = global::AutoGen.Anthropic.Utils.AnthropicConstants.Claude35Sonnet; + } } diff --git a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientAgentTest.cs b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientAgentTest.cs index 91097d7485df..cc33f6e23b92 100644 --- a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientAgentTest.cs +++ b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientAgentTest.cs @@ -8,6 +8,8 @@ using AutoGen.Tests; using FluentAssertions; +using Microsoft.AutoGen.Extensions.Anthropic.Tests; + namespace AutoGen.Anthropic.Tests; public class AnthropicClientAgentTest diff --git a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientTest.cs b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientTest.cs index c98a81079854..a1b41d7adc3c 100644 --- a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientTest.cs +++ b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicClientTest.cs @@ -5,13 +5,15 @@ using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; -using AutoGen.Anthropic.DTO; -using AutoGen.Anthropic.Utils; using AutoGen.Tests; using FluentAssertions; using Xunit; -namespace AutoGen.Anthropic.Tests; +using AutoGen.Anthropic; +using AutoGen.Anthropic.DTO; +using AutoGen.Anthropic.Utils; + +namespace Microsoft.AutoGen.Extensions.Anthropic.Tests; public class AnthropicClientTests { diff --git a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestFunctionCalls.cs b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestFunctionCalls.cs index b753aa8ab0cf..dbe39dc43377 100644 --- a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestFunctionCalls.cs +++ b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestFunctionCalls.cs @@ -5,7 +5,7 @@ using System.Text.Json.Serialization; using AutoGen.Core; -namespace AutoGen.Anthropic.Tests; +namespace Microsoft.AutoGen.Extensions.Anthropic.Tests; public partial class AnthropicTestFunctionCalls { diff --git a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestUtils.cs b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestUtils.cs index 6849733ff652..1c5dd6228a4d 100644 --- a/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestUtils.cs +++ b/dotnet/test/AutoGen.Anthropic.Tests/AnthropicTestUtils.cs @@ -3,7 +3,7 @@ using AutoGen.Anthropic.DTO; -namespace AutoGen.Anthropic.Tests; +namespace Microsoft.AutoGen.Extensions.Anthropic.Tests; public static class AnthropicTestUtils { diff --git a/dotnet/test/AutoGen.Anthropic.Tests/AutoGen.Anthropic.Tests.csproj b/dotnet/test/AutoGen.Anthropic.Tests/AutoGen.Anthropic.Tests.csproj index ac9617c1a573..d1bdce04e326 100644 --- a/dotnet/test/AutoGen.Anthropic.Tests/AutoGen.Anthropic.Tests.csproj +++ b/dotnet/test/AutoGen.Anthropic.Tests/AutoGen.Anthropic.Tests.csproj @@ -11,6 +11,7 @@ +