Skip to content

Commit 9de3709

Browse files
authored
[realtime] Address serialization issue with ConversationToolChoice (#282)
1 parent fa2c26f commit 9de3709

File tree

7 files changed

+46
-7
lines changed

7 files changed

+46
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- 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)
1616
- Several types have been renamed for consistency and clarity.
1717
- `ConversationRateLimitsUpdate` (previously `ConversationRateLimitsUpdatedUpdate`) now includes named `RequestDetails` and `TokenDetails` properties, mapping to the corresponding named items in the underlying `rate_limits` command payload.
18+
- Serialization and deserialization of `ConversationToolChoice` literal values (such as `"required"`) is fixed
1819

1920
### Other Changes
2021

api/OpenAI.netstandard2.0.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,10 +2755,11 @@ public class ConversationToolChoice : IJsonModel<ConversationToolChoice>, IPersi
27552755
BinaryData IPersistableModel<ConversationToolChoice>.Write(ModelReaderWriterOptions options);
27562756
}
27572757
public enum ConversationToolChoiceKind {
2758-
Auto = 0,
2759-
None = 1,
2760-
Required = 2,
2761-
Function = 3
2758+
Unknown = 0,
2759+
Auto = 1,
2760+
None = 2,
2761+
Required = 3,
2762+
Function = 4
27622763
}
27632764
public readonly partial struct ConversationToolKind : IEquatable<ConversationToolKind> {
27642765
private readonly object _dummy;

src/Custom/RealtimeConversation/ConversationSessionOptions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public ConversationToolChoice ToolChoice
2626
get => ConversationToolChoice.FromBinaryData(_internalToolChoice);
2727
set
2828
{
29-
_internalToolChoice = ModelReaderWriter.Write(value);
29+
_internalToolChoice = value is not null
30+
? ModelReaderWriter.Write(value)
31+
: null;
3032
}
3133
}
3234

src/Custom/RealtimeConversation/ConversationToolChoice.Serialization.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal static void SerializeConversationToolChoice(ConversationToolChoice inst
2929
}
3030
else
3131
{
32-
writer.WriteStringValue(instance.Kind.ToString());
32+
writer.WriteStringValue(instance.Kind.ToSerialString());
3333
}
3434
}
3535

@@ -50,7 +50,7 @@ internal static ConversationToolChoice DeserializeConversationToolChoice(JsonEle
5050
return choiceObject switch
5151
{
5252
InternalRealtimeToolChoiceFunctionObject => new(ConversationToolChoiceKind.Function, choiceObject),
53-
_ => null,
53+
_ => new(ConversationToolChoiceKind.Unknown, choiceObject),
5454
};
5555
}
5656
return null;

src/Custom/RealtimeConversation/ConversationToolChoice.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ internal ConversationToolChoice(ConversationToolChoiceKind choiceKind, InternalR
2626
Kind = choiceKind;
2727
_objectToolChoice = objectToolChoice;
2828
}
29+
30+
internal ConversationToolChoice() : this(ConversationToolChoiceKind.Unknown, null)
31+
{
32+
}
2933
}

src/Custom/RealtimeConversation/ConversationToolChoiceKind.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ namespace OpenAI.RealtimeConversation;
88
[CodeGenModel("RealtimeToolChoiceLiteral")]
99
public enum ConversationToolChoiceKind
1010
{
11+
Unknown,
1112
[CodeGenMember("Auto")]
1213
Auto,
1314
[CodeGenMember("None")]
1415
None,
1516
[CodeGenMember("Required")]
1617
Required,
18+
[CodeGenMember("Function")]
1719
Function,
1820
}

tests/RealtimeConversation/ConversationSmokeTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,35 @@ public class ConversationSmokeTests : ConversationTestFixtureBase
1818
public ConversationSmokeTests(bool isAsync) : base(isAsync)
1919
{ }
2020

21+
[Test]
22+
public void ToolChoiceSerializationInSessionOptionsWorks()
23+
{
24+
foreach((ConversationToolChoice toolChoice, string expected) in new (ConversationToolChoice, string)[]
25+
{
26+
(null, "{}"),
27+
(ConversationToolChoice.CreateNoneToolChoice(), @"{""tool_choice"":""none""}"),
28+
(ConversationToolChoice.CreateAutoToolChoice(), @"{""tool_choice"":""auto""}"),
29+
(ConversationToolChoice.CreateRequiredToolChoice(), @"{""tool_choice"":""required""}"),
30+
(ConversationToolChoice.CreateFunctionToolChoice("foo"), @"{""function"":{""name"":""foo""}")
31+
})
32+
{
33+
ConversationSessionOptions options = new()
34+
{
35+
ToolChoice = toolChoice,
36+
};
37+
Assert.That(ModelReaderWriter.Write(options).ToString(), Does.Contain(expected));
38+
}
39+
40+
ConversationToolChoice mrwToolChoice = ModelReaderWriter.Read<ConversationToolChoice>(
41+
BinaryData.FromString("""
42+
{
43+
"type":"some_manual_type"
44+
}
45+
"""));
46+
Assert.That(mrwToolChoice.Kind, Is.EqualTo(ConversationToolChoiceKind.Unknown));
47+
Assert.That(ModelReaderWriter.Write(mrwToolChoice).ToString(), Does.Contain(@"""type"":""some_manual_type"""));
48+
}
49+
2150
[Test]
2251
public void ItemCreation()
2352
{

0 commit comments

Comments
 (0)