diff --git a/CHANGELOG.md b/CHANGELOG.md index f311bd28..d72ced23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Made improvements to the experimental Realtime API. Please note this features area is currently under rapid development and not all changes may be reflected here. (commit_hash) - Several types have been renamed for consistency and clarity. - `ConversationRateLimitsUpdate` (previously `ConversationRateLimitsUpdatedUpdate`) now includes named `RequestDetails` and `TokenDetails` properties, mapping to the corresponding named items in the underlying `rate_limits` command payload. + - Serialization and deserialization of `ConversationToolChoice` literal values (such as `"required"`) is fixed ### Other Changes diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs index 90fdcfcd..8fc8ec6e 100644 --- a/api/OpenAI.netstandard2.0.cs +++ b/api/OpenAI.netstandard2.0.cs @@ -2755,10 +2755,11 @@ public class ConversationToolChoice : IJsonModel, IPersi BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); } public enum ConversationToolChoiceKind { - Auto = 0, - None = 1, - Required = 2, - Function = 3 + Unknown = 0, + Auto = 1, + None = 2, + Required = 3, + Function = 4 } public readonly partial struct ConversationToolKind : IEquatable { private readonly object _dummy; diff --git a/src/Custom/RealtimeConversation/ConversationSessionOptions.cs b/src/Custom/RealtimeConversation/ConversationSessionOptions.cs index a4b4d122..14f2abeb 100644 --- a/src/Custom/RealtimeConversation/ConversationSessionOptions.cs +++ b/src/Custom/RealtimeConversation/ConversationSessionOptions.cs @@ -26,7 +26,9 @@ public ConversationToolChoice ToolChoice get => ConversationToolChoice.FromBinaryData(_internalToolChoice); set { - _internalToolChoice = ModelReaderWriter.Write(value); + _internalToolChoice = value is not null + ? ModelReaderWriter.Write(value) + : null; } } diff --git a/src/Custom/RealtimeConversation/ConversationToolChoice.Serialization.cs b/src/Custom/RealtimeConversation/ConversationToolChoice.Serialization.cs index 267f18f4..d0367f25 100644 --- a/src/Custom/RealtimeConversation/ConversationToolChoice.Serialization.cs +++ b/src/Custom/RealtimeConversation/ConversationToolChoice.Serialization.cs @@ -29,7 +29,7 @@ internal static void SerializeConversationToolChoice(ConversationToolChoice inst } else { - writer.WriteStringValue(instance.Kind.ToString()); + writer.WriteStringValue(instance.Kind.ToSerialString()); } } @@ -50,7 +50,7 @@ internal static ConversationToolChoice DeserializeConversationToolChoice(JsonEle return choiceObject switch { InternalRealtimeToolChoiceFunctionObject => new(ConversationToolChoiceKind.Function, choiceObject), - _ => null, + _ => new(ConversationToolChoiceKind.Unknown, choiceObject), }; } return null; diff --git a/src/Custom/RealtimeConversation/ConversationToolChoice.cs b/src/Custom/RealtimeConversation/ConversationToolChoice.cs index 58508579..10848654 100644 --- a/src/Custom/RealtimeConversation/ConversationToolChoice.cs +++ b/src/Custom/RealtimeConversation/ConversationToolChoice.cs @@ -26,4 +26,8 @@ internal ConversationToolChoice(ConversationToolChoiceKind choiceKind, InternalR Kind = choiceKind; _objectToolChoice = objectToolChoice; } + + internal ConversationToolChoice() : this(ConversationToolChoiceKind.Unknown, null) + { + } } \ No newline at end of file diff --git a/src/Custom/RealtimeConversation/ConversationToolChoiceKind.cs b/src/Custom/RealtimeConversation/ConversationToolChoiceKind.cs index ab6f431c..25a9a43c 100644 --- a/src/Custom/RealtimeConversation/ConversationToolChoiceKind.cs +++ b/src/Custom/RealtimeConversation/ConversationToolChoiceKind.cs @@ -8,11 +8,13 @@ namespace OpenAI.RealtimeConversation; [CodeGenModel("RealtimeToolChoiceLiteral")] public enum ConversationToolChoiceKind { + Unknown, [CodeGenMember("Auto")] Auto, [CodeGenMember("None")] None, [CodeGenMember("Required")] Required, + [CodeGenMember("Function")] Function, } \ No newline at end of file diff --git a/tests/RealtimeConversation/ConversationSmokeTests.cs b/tests/RealtimeConversation/ConversationSmokeTests.cs index 136ec784..72bd3252 100644 --- a/tests/RealtimeConversation/ConversationSmokeTests.cs +++ b/tests/RealtimeConversation/ConversationSmokeTests.cs @@ -18,6 +18,35 @@ public class ConversationSmokeTests : ConversationTestFixtureBase public ConversationSmokeTests(bool isAsync) : base(isAsync) { } + [Test] + public void ToolChoiceSerializationInSessionOptionsWorks() + { + foreach((ConversationToolChoice toolChoice, string expected) in new (ConversationToolChoice, string)[] + { + (null, "{}"), + (ConversationToolChoice.CreateNoneToolChoice(), @"{""tool_choice"":""none""}"), + (ConversationToolChoice.CreateAutoToolChoice(), @"{""tool_choice"":""auto""}"), + (ConversationToolChoice.CreateRequiredToolChoice(), @"{""tool_choice"":""required""}"), + (ConversationToolChoice.CreateFunctionToolChoice("foo"), @"{""function"":{""name"":""foo""}") + }) + { + ConversationSessionOptions options = new() + { + ToolChoice = toolChoice, + }; + Assert.That(ModelReaderWriter.Write(options).ToString(), Does.Contain(expected)); + } + + ConversationToolChoice mrwToolChoice = ModelReaderWriter.Read( + BinaryData.FromString(""" + { + "type":"some_manual_type" + } + """)); + Assert.That(mrwToolChoice.Kind, Is.EqualTo(ConversationToolChoiceKind.Unknown)); + Assert.That(ModelReaderWriter.Write(mrwToolChoice).ToString(), Does.Contain(@"""type"":""some_manual_type""")); + } + [Test] public void ItemCreation() {