Skip to content

Commit c4c6393

Browse files
committed
oai: new responses props
1 parent 808679b commit c4c6393

File tree

8 files changed

+559
-4
lines changed

8 files changed

+559
-4
lines changed

src/LlmTornado/Code/PartialModels.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,12 @@ public enum ChatRequestServiceTiers
647647
/// </summary>
648648
[EnumMember(Value = "flex")]
649649
Flex,
650+
651+
/// <summary>
652+
/// Scale tier processing with higher rate limits and guaranteed latency SLA.
653+
/// </summary>
654+
[EnumMember(Value = "scale")]
655+
Scale,
650656

651657
/// <summary>
652658
/// Additional option for service_tier supported by Groq
@@ -751,6 +757,12 @@ public enum ChatReasoningFormats
751757
[JsonConverter(typeof(StringEnumConverter))]
752758
public enum PromptCacheRetention
753759
{
760+
/// <summary>
761+
/// In-memory cache retention.
762+
/// </summary>
763+
[EnumMember(Value = "in-memory")]
764+
InMemory,
765+
754766
/// <summary>
755767
/// 24-hour cache retention. Keeps cached prefixes active for up to 24 hours.
756768
/// </summary>

src/LlmTornado/Responses/Enums.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ public enum ResponseReasoningEfforts
6565
[EnumMember(Value = "none")]
6666
None,
6767

68+
/// <summary>
69+
/// Minimal reasoning effort.
70+
/// </summary>
71+
[EnumMember(Value = "minimal")]
72+
Minimal,
73+
6874
/// <summary>
6975
/// Low reasoning effort.
7076
/// </summary>
@@ -187,7 +193,35 @@ public enum ResponseIncludeFields
187193
/// Includes an encrypted version of reasoning tokens in reasoning item outputs.
188194
/// </summary>
189195
[EnumMember(Value = "reasoning.encrypted_content")]
190-
ReasoningEncryptedContent
196+
ReasoningEncryptedContent,
197+
198+
/// <summary>
199+
/// Include the search results of the web search tool call.
200+
/// </summary>
201+
[EnumMember(Value = "web_search_call.results")]
202+
WebSearchCallResults
203+
}
204+
205+
/// <summary>
206+
/// Labels an assistant message as intermediate commentary or the final answer.
207+
/// For models like gpt-5.3-codex and beyond, when sending follow-up requests,
208+
/// preserve and resend phase on all assistant messages — dropping it can degrade performance.
209+
/// Not used for user messages.
210+
/// </summary>
211+
[JsonConverter(typeof(StringEnumConverter))]
212+
public enum ResponsePhases
213+
{
214+
/// <summary>
215+
/// Intermediate assistant commentary.
216+
/// </summary>
217+
[EnumMember(Value = "commentary")]
218+
Commentary,
219+
220+
/// <summary>
221+
/// The final assistant answer.
222+
/// </summary>
223+
[EnumMember(Value = "final_answer")]
224+
FinalAnswer
191225
}
192226

193227
/// <summary>
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System;
2+
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
4+
5+
namespace LlmTornado.Responses;
6+
7+
/// <summary>
8+
/// Represents the conversation that a response belongs to.
9+
/// Can be a plain string (conversation ID) or an object with an <c>id</c> field.
10+
/// </summary>
11+
[JsonConverter(typeof(ResponseConversationJsonConverter))]
12+
public interface IResponseConversation
13+
{
14+
/// <summary>
15+
/// The unique ID of the conversation.
16+
/// </summary>
17+
string Id { get; }
18+
}
19+
20+
/// <summary>
21+
/// String-form conversation reference — serializes as a plain string.
22+
/// </summary>
23+
public class StringResponseConversation : IResponseConversation
24+
{
25+
/// <inheritdoc/>
26+
public string Id { get; set; }
27+
28+
/// <summary>
29+
/// Creates a new string conversation reference.
30+
/// </summary>
31+
public StringResponseConversation(string id)
32+
{
33+
Id = id;
34+
}
35+
36+
/// <summary>
37+
/// Creates an empty string conversation reference.
38+
/// </summary>
39+
public StringResponseConversation()
40+
{
41+
Id = string.Empty;
42+
}
43+
44+
/// <summary>
45+
/// Implicit conversion from string.
46+
/// </summary>
47+
public static implicit operator StringResponseConversation(string id) => new(id);
48+
49+
/// <summary>
50+
/// Implicit conversion to string.
51+
/// </summary>
52+
public static implicit operator string(StringResponseConversation conversation) => conversation.Id;
53+
}
54+
55+
/// <summary>
56+
/// Object-form conversation reference — serializes as <c>{ "id": "..." }</c>.
57+
/// This is the form returned in API responses.
58+
/// </summary>
59+
public class ObjectResponseConversation : IResponseConversation
60+
{
61+
/// <inheritdoc/>
62+
[JsonProperty("id")]
63+
public string Id { get; set; }
64+
65+
/// <summary>
66+
/// Creates a new object conversation reference.
67+
/// </summary>
68+
public ObjectResponseConversation(string id)
69+
{
70+
Id = id;
71+
}
72+
73+
/// <summary>
74+
/// Creates an empty object conversation reference.
75+
/// </summary>
76+
public ObjectResponseConversation()
77+
{
78+
Id = string.Empty;
79+
}
80+
}
81+
82+
/// <summary>
83+
/// Handles serialization and deserialization of <see cref="IResponseConversation"/>.
84+
/// Writes <see cref="StringResponseConversation"/> as a plain JSON string,
85+
/// <see cref="ObjectResponseConversation"/> as <c>{ "id": "..." }</c>.
86+
/// Reads a JSON string token as <see cref="StringResponseConversation"/>,
87+
/// a JSON object token as <see cref="ObjectResponseConversation"/>.
88+
/// </summary>
89+
internal class ResponseConversationJsonConverter : JsonConverter<IResponseConversation>
90+
{
91+
public override void WriteJson(JsonWriter writer, IResponseConversation? value, JsonSerializer serializer)
92+
{
93+
if (value is null)
94+
{
95+
writer.WriteNull();
96+
return;
97+
}
98+
99+
switch (value)
100+
{
101+
case StringResponseConversation str:
102+
writer.WriteValue(str.Id);
103+
break;
104+
case ObjectResponseConversation obj:
105+
writer.WriteStartObject();
106+
writer.WritePropertyName("id");
107+
writer.WriteValue(obj.Id);
108+
writer.WriteEndObject();
109+
break;
110+
default:
111+
throw new JsonSerializationException($"Unexpected conversation type: {value.GetType()}");
112+
}
113+
}
114+
115+
public override IResponseConversation? ReadJson(JsonReader reader, Type objectType, IResponseConversation? existingValue, bool hasExistingValue, JsonSerializer serializer)
116+
{
117+
if (reader.TokenType is JsonToken.Null)
118+
{
119+
return null;
120+
}
121+
122+
if (reader.TokenType is JsonToken.String)
123+
{
124+
string? id = reader.Value?.ToString();
125+
return id is not null ? new StringResponseConversation(id) : null;
126+
}
127+
128+
if (reader.TokenType is JsonToken.StartObject)
129+
{
130+
JObject jo = JObject.Load(reader);
131+
string? id = jo["id"]?.ToString();
132+
return id is not null ? new ObjectResponseConversation(id) : null;
133+
}
134+
135+
throw new JsonSerializationException($"Unexpected token type for conversation: {reader.TokenType}");
136+
}
137+
138+
public override bool CanRead => true;
139+
public override bool CanWrite => true;
140+
}

0 commit comments

Comments
 (0)