diff --git a/api/OpenAI.net8.0.cs b/api/OpenAI.net8.0.cs index dc541eb90..c72dc3873 100644 --- a/api/OpenAI.net8.0.cs +++ b/api/OpenAI.net8.0.cs @@ -4991,7 +4991,7 @@ public enum MessageStatus { } [Experimental("OPENAI001")] public class OpenAIResponse : IJsonModel, IPersistableModel { - public bool? Background { get; } + public bool? BackgroundModeEnabled { get; } public DateTimeOffset CreatedAt { get; } public string EndUserId { get; } public ResponseError Error { get; } @@ -5069,7 +5069,7 @@ public class OpenAIResponseClient { [Experimental("OPENAI001")] public static class OpenAIResponsesModelFactory { public static MessageResponseItem MessageResponseItem(string id = null, MessageRole role = MessageRole.Assistant, MessageStatus? status = null); - public static OpenAIResponse OpenAIResponse(string id = null, DateTimeOffset createdAt = default, ResponseStatus? status = null, ResponseError error = null, ResponseTokenUsage usage = null, string endUserId = null, ResponseReasoningOptions reasoningOptions = null, int? maxOutputTokenCount = null, ResponseTextOptions textOptions = null, ResponseTruncationMode? truncationMode = null, ResponseIncompleteStatusDetails incompleteStatusDetails = null, IEnumerable outputItems = null, bool parallelToolCallsEnabled = false, ResponseToolChoice toolChoice = null, string model = null, IDictionary metadata = null, float? temperature = null, float? topP = null, ResponseServiceTier? serviceTier = null, string previousResponseId = null, bool? background = null, string instructions = null, IEnumerable tools = null); + public static OpenAIResponse OpenAIResponse(string id = null, DateTimeOffset createdAt = default, ResponseStatus? status = null, ResponseError error = null, ResponseTokenUsage usage = null, string endUserId = null, ResponseReasoningOptions reasoningOptions = null, int? maxOutputTokenCount = null, ResponseTextOptions textOptions = null, ResponseTruncationMode? truncationMode = null, ResponseIncompleteStatusDetails incompleteStatusDetails = null, IEnumerable outputItems = null, bool parallelToolCallsEnabled = false, ResponseToolChoice toolChoice = null, string model = null, IDictionary metadata = null, float? temperature = null, float? topP = null, ResponseServiceTier? serviceTier = null, string previousResponseId = null, bool? backgroundModeEnabled = null, string instructions = null, IEnumerable tools = null); public static ReasoningResponseItem ReasoningResponseItem(string id = null, string encryptedContent = null, ReasoningStatus? status = null, IEnumerable summaryParts = null); public static ReasoningResponseItem ReasoningResponseItem(string id = null, string encryptedContent = null, ReasoningStatus? status = null, string summaryText = null); public static ReferenceResponseItem ReferenceResponseItem(string id = null); @@ -5154,7 +5154,7 @@ public enum ResponseContentPartKind { } [Experimental("OPENAI001")] public class ResponseCreationOptions : IJsonModel, IPersistableModel { - public bool? Background { get; set; } + public bool? BackgroundModeEnabled { get; set; } public string EndUserId { get; set; } public string Instructions { get; set; } public int? MaxOutputTokenCount { get; set; } diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs index 48fa38262..085898631 100644 --- a/api/OpenAI.netstandard2.0.cs +++ b/api/OpenAI.netstandard2.0.cs @@ -4390,7 +4390,7 @@ public enum MessageStatus { Incomplete = 2 } public class OpenAIResponse : IJsonModel, IPersistableModel { - public bool? Background { get; } + public bool? BackgroundModeEnabled { get; } public DateTimeOffset CreatedAt { get; } public string EndUserId { get; } public ResponseError Error { get; } @@ -4465,7 +4465,7 @@ public class OpenAIResponseClient { } public static class OpenAIResponsesModelFactory { public static MessageResponseItem MessageResponseItem(string id = null, MessageRole role = MessageRole.Assistant, MessageStatus? status = null); - public static OpenAIResponse OpenAIResponse(string id = null, DateTimeOffset createdAt = default, ResponseStatus? status = null, ResponseError error = null, ResponseTokenUsage usage = null, string endUserId = null, ResponseReasoningOptions reasoningOptions = null, int? maxOutputTokenCount = null, ResponseTextOptions textOptions = null, ResponseTruncationMode? truncationMode = null, ResponseIncompleteStatusDetails incompleteStatusDetails = null, IEnumerable outputItems = null, bool parallelToolCallsEnabled = false, ResponseToolChoice toolChoice = null, string model = null, IDictionary metadata = null, float? temperature = null, float? topP = null, ResponseServiceTier? serviceTier = null, string previousResponseId = null, bool? background = null, string instructions = null, IEnumerable tools = null); + public static OpenAIResponse OpenAIResponse(string id = null, DateTimeOffset createdAt = default, ResponseStatus? status = null, ResponseError error = null, ResponseTokenUsage usage = null, string endUserId = null, ResponseReasoningOptions reasoningOptions = null, int? maxOutputTokenCount = null, ResponseTextOptions textOptions = null, ResponseTruncationMode? truncationMode = null, ResponseIncompleteStatusDetails incompleteStatusDetails = null, IEnumerable outputItems = null, bool parallelToolCallsEnabled = false, ResponseToolChoice toolChoice = null, string model = null, IDictionary metadata = null, float? temperature = null, float? topP = null, ResponseServiceTier? serviceTier = null, string previousResponseId = null, bool? backgroundModeEnabled = null, string instructions = null, IEnumerable tools = null); public static ReasoningResponseItem ReasoningResponseItem(string id = null, string encryptedContent = null, ReasoningStatus? status = null, IEnumerable summaryParts = null); public static ReasoningResponseItem ReasoningResponseItem(string id = null, string encryptedContent = null, ReasoningStatus? status = null, string summaryText = null); public static ReferenceResponseItem ReferenceResponseItem(string id = null); @@ -4542,7 +4542,7 @@ public enum ResponseContentPartKind { Refusal = 5 } public class ResponseCreationOptions : IJsonModel, IPersistableModel { - public bool? Background { get; set; } + public bool? BackgroundModeEnabled { get; set; } public string EndUserId { get; set; } public string Instructions { get; set; } public int? MaxOutputTokenCount { get; set; } diff --git a/src/Custom/Responses/OpenAIResponse.cs b/src/Custom/Responses/OpenAIResponse.cs index 86cd5318e..bf445e677 100644 --- a/src/Custom/Responses/OpenAIResponse.cs +++ b/src/Custom/Responses/OpenAIResponse.cs @@ -14,6 +14,10 @@ namespace OpenAI.Responses; [CodeGenSuppress("OutputText")] public partial class OpenAIResponse { + // CUSTOM: Renamed. + [CodeGenMember("Background")] + public bool? BackgroundModeEnabled { get; } + // CUSTOM: Renamed. [CodeGenMember("User")] public string EndUserId { get; } diff --git a/src/Custom/Responses/OpenAIResponsesModelFactory.cs b/src/Custom/Responses/OpenAIResponsesModelFactory.cs index 7c2b2c819..0dddb4fdc 100644 --- a/src/Custom/Responses/OpenAIResponsesModelFactory.cs +++ b/src/Custom/Responses/OpenAIResponsesModelFactory.cs @@ -32,7 +32,7 @@ public static OpenAIResponse OpenAIResponse( float? topP = null, ResponseServiceTier? serviceTier = null, string previousResponseId = null, - bool? background = null, + bool? backgroundModeEnabled = null, string instructions = null, IEnumerable tools = null) { @@ -46,7 +46,7 @@ public static OpenAIResponse OpenAIResponse( topP: topP, serviceTier: serviceTier, previousResponseId: previousResponseId, - background: background, + backgroundModeEnabled: backgroundModeEnabled, instructions: instructions, tools: tools.ToList(), id: id, diff --git a/src/Custom/Responses/ResponseCreationOptions.cs b/src/Custom/Responses/ResponseCreationOptions.cs index dadd28029..3d8893201 100644 --- a/src/Custom/Responses/ResponseCreationOptions.cs +++ b/src/Custom/Responses/ResponseCreationOptions.cs @@ -33,6 +33,10 @@ public partial class ResponseCreationOptions // CUSTOM: Made internal. This value comes from a parameter on the client method. internal bool? Stream { get; set; } + // CUSTOM: Renamed. + [CodeGenMember("Background")] + public bool? BackgroundModeEnabled { get; set; } + // CUSTOM: Renamed. [CodeGenMember("User")] public string EndUserId { get; set; } diff --git a/src/Generated/Models/Responses/OpenAIResponse.Serialization.cs b/src/Generated/Models/Responses/OpenAIResponse.Serialization.cs index 50a01c394..6e409249d 100644 --- a/src/Generated/Models/Responses/OpenAIResponse.Serialization.cs +++ b/src/Generated/Models/Responses/OpenAIResponse.Serialization.cs @@ -110,10 +110,10 @@ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWrit writer.WritePropertyName("reasoning"u8); writer.WriteObjectValue(ReasoningOptions, options); } - if (Optional.IsDefined(Background) && _additionalBinaryDataProperties?.ContainsKey("background") != true) + if (Optional.IsDefined(BackgroundModeEnabled) && _additionalBinaryDataProperties?.ContainsKey("background") != true) { writer.WritePropertyName("background"u8); - writer.WriteBooleanValue(Background.Value); + writer.WriteBooleanValue(BackgroundModeEnabled.Value); } if (Optional.IsDefined(MaxOutputTokenCount) && _additionalBinaryDataProperties?.ContainsKey("max_output_tokens") != true) { @@ -263,7 +263,7 @@ internal static OpenAIResponse DeserializeOpenAIResponse(JsonElement element, Mo string previousResponseId = default; string model = default; ResponseReasoningOptions reasoningOptions = default; - bool? background = default; + bool? backgroundModeEnabled = default; int? maxOutputTokenCount = default; string instructions = default; ResponseTextOptions textOptions = default; @@ -372,10 +372,10 @@ internal static OpenAIResponse DeserializeOpenAIResponse(JsonElement element, Mo { if (prop.Value.ValueKind == JsonValueKind.Null) { - background = null; + backgroundModeEnabled = null; continue; } - background = prop.Value.GetBoolean(); + backgroundModeEnabled = prop.Value.GetBoolean(); continue; } if (prop.NameEquals("max_output_tokens"u8)) @@ -520,7 +520,7 @@ internal static OpenAIResponse DeserializeOpenAIResponse(JsonElement element, Mo previousResponseId, model, reasoningOptions, - background, + backgroundModeEnabled, maxOutputTokenCount, instructions, textOptions, diff --git a/src/Generated/Models/Responses/OpenAIResponse.cs b/src/Generated/Models/Responses/OpenAIResponse.cs index 0c601460f..6e0588263 100644 --- a/src/Generated/Models/Responses/OpenAIResponse.cs +++ b/src/Generated/Models/Responses/OpenAIResponse.cs @@ -31,7 +31,7 @@ internal OpenAIResponse(IDictionary metadata, float? temperature ParallelToolCallsEnabled = parallelToolCallsEnabled; } - internal OpenAIResponse(IDictionary metadata, float? temperature, float? topP, string endUserId, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? background, int? maxOutputTokenCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, ResponseTruncationMode? truncationMode, string id, string @object, ResponseStatus? status, DateTimeOffset createdAt, ResponseError error, ResponseIncompleteStatusDetails incompleteStatusDetails, IList outputItems, ResponseTokenUsage usage, bool parallelToolCallsEnabled, IDictionary additionalBinaryDataProperties) + internal OpenAIResponse(IDictionary metadata, float? temperature, float? topP, string endUserId, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? backgroundModeEnabled, int? maxOutputTokenCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, ResponseTruncationMode? truncationMode, string id, string @object, ResponseStatus? status, DateTimeOffset createdAt, ResponseError error, ResponseIncompleteStatusDetails incompleteStatusDetails, IList outputItems, ResponseTokenUsage usage, bool parallelToolCallsEnabled, IDictionary additionalBinaryDataProperties) { // Plugin customization: ensure initialization of collections Metadata = metadata ?? new ChangeTrackingDictionary(); @@ -42,7 +42,7 @@ internal OpenAIResponse(IDictionary metadata, float? temperature PreviousResponseId = previousResponseId; Model = model; ReasoningOptions = reasoningOptions; - Background = background; + BackgroundModeEnabled = backgroundModeEnabled; MaxOutputTokenCount = maxOutputTokenCount; Instructions = instructions; TextOptions = textOptions; @@ -71,8 +71,6 @@ internal OpenAIResponse(IDictionary metadata, float? temperature public string PreviousResponseId { get; } - public bool? Background { get; } - public string Instructions { get; } public IList Tools { get; } diff --git a/src/Generated/Models/Responses/ResponseCreationOptions.Serialization.cs b/src/Generated/Models/Responses/ResponseCreationOptions.Serialization.cs index d5e4d9f2c..ffbba6e7a 100644 --- a/src/Generated/Models/Responses/ResponseCreationOptions.Serialization.cs +++ b/src/Generated/Models/Responses/ResponseCreationOptions.Serialization.cs @@ -81,10 +81,10 @@ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWrit writer.WritePropertyName("reasoning"u8); writer.WriteObjectValue(ReasoningOptions, options); } - if (Optional.IsDefined(Background) && _additionalBinaryDataProperties?.ContainsKey("background") != true) + if (Optional.IsDefined(BackgroundModeEnabled) && _additionalBinaryDataProperties?.ContainsKey("background") != true) { writer.WritePropertyName("background"u8); - writer.WriteBooleanValue(Background.Value); + writer.WriteBooleanValue(BackgroundModeEnabled.Value); } if (Optional.IsDefined(MaxOutputTokenCount) && _additionalBinaryDataProperties?.ContainsKey("max_output_tokens") != true) { @@ -205,7 +205,7 @@ internal static ResponseCreationOptions DeserializeResponseCreationOptions(JsonE string previousResponseId = default; string model = default; ResponseReasoningOptions reasoningOptions = default; - bool? background = default; + bool? backgroundModeEnabled = default; int? maxOutputTokenCount = default; string instructions = default; ResponseTextOptions textOptions = default; @@ -304,10 +304,10 @@ internal static ResponseCreationOptions DeserializeResponseCreationOptions(JsonE { if (prop.Value.ValueKind == JsonValueKind.Null) { - background = null; + backgroundModeEnabled = null; continue; } - background = prop.Value.GetBoolean(); + backgroundModeEnabled = prop.Value.GetBoolean(); continue; } if (prop.NameEquals("max_output_tokens"u8)) @@ -438,7 +438,7 @@ internal static ResponseCreationOptions DeserializeResponseCreationOptions(JsonE previousResponseId, model, reasoningOptions, - background, + backgroundModeEnabled, maxOutputTokenCount, instructions, textOptions, diff --git a/src/Generated/Models/Responses/ResponseCreationOptions.cs b/src/Generated/Models/Responses/ResponseCreationOptions.cs index 89f556ef0..e24170b37 100644 --- a/src/Generated/Models/Responses/ResponseCreationOptions.cs +++ b/src/Generated/Models/Responses/ResponseCreationOptions.cs @@ -14,7 +14,7 @@ public partial class ResponseCreationOptions { private protected IDictionary _additionalBinaryDataProperties; - internal ResponseCreationOptions(IDictionary metadata, float? temperature, float? topP, string endUserId, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? background, int? maxOutputTokenCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, ResponseTruncationMode? truncationMode, IList input, IList include, bool? parallelToolCallsEnabled, bool? storedOutputEnabled, bool? stream, IDictionary additionalBinaryDataProperties) + internal ResponseCreationOptions(IDictionary metadata, float? temperature, float? topP, string endUserId, ResponseServiceTier? serviceTier, string previousResponseId, string model, ResponseReasoningOptions reasoningOptions, bool? backgroundModeEnabled, int? maxOutputTokenCount, string instructions, ResponseTextOptions textOptions, IList tools, ResponseToolChoice toolChoice, ResponseTruncationMode? truncationMode, IList input, IList include, bool? parallelToolCallsEnabled, bool? storedOutputEnabled, bool? stream, IDictionary additionalBinaryDataProperties) { // Plugin customization: ensure initialization of collections Metadata = metadata ?? new ChangeTrackingDictionary(); @@ -25,7 +25,7 @@ internal ResponseCreationOptions(IDictionary metadata, float? te PreviousResponseId = previousResponseId; Model = model; ReasoningOptions = reasoningOptions; - Background = background; + BackgroundModeEnabled = backgroundModeEnabled; MaxOutputTokenCount = maxOutputTokenCount; Instructions = instructions; TextOptions = textOptions; @@ -50,8 +50,6 @@ internal ResponseCreationOptions(IDictionary metadata, float? te public string PreviousResponseId { get; set; } - public bool? Background { get; set; } - public string Instructions { get; set; } internal IDictionary SerializedAdditionalRawData diff --git a/src/Generated/OpenAIModelFactory.cs b/src/Generated/OpenAIModelFactory.cs index cec96cabc..bc1a8918a 100644 --- a/src/Generated/OpenAIModelFactory.cs +++ b/src/Generated/OpenAIModelFactory.cs @@ -627,7 +627,7 @@ public static McpToolDefinition McpToolDefinition(string name = default, string return new McpToolDefinition(name, description, inputSchema, annotations, additionalBinaryDataProperties: null); } - public static OpenAIResponse OpenAIResponse(IDictionary metadata = default, float? temperature = default, float? topP = default, string endUserId = default, ResponseServiceTier? serviceTier = default, string previousResponseId = default, string model = default, ResponseReasoningOptions reasoningOptions = default, bool? background = default, int? maxOutputTokenCount = default, string instructions = default, ResponseTextOptions textOptions = default, IEnumerable tools = default, ResponseToolChoice toolChoice = default, ResponseTruncationMode? truncationMode = default, string id = default, string @object = default, ResponseStatus? status = default, DateTimeOffset createdAt = default, ResponseError error = default, ResponseIncompleteStatusDetails incompleteStatusDetails = default, IEnumerable outputItems = default, ResponseTokenUsage usage = default, bool parallelToolCallsEnabled = default) + public static OpenAIResponse OpenAIResponse(IDictionary metadata = default, float? temperature = default, float? topP = default, string endUserId = default, ResponseServiceTier? serviceTier = default, string previousResponseId = default, string model = default, ResponseReasoningOptions reasoningOptions = default, bool? backgroundModeEnabled = default, int? maxOutputTokenCount = default, string instructions = default, ResponseTextOptions textOptions = default, IEnumerable tools = default, ResponseToolChoice toolChoice = default, ResponseTruncationMode? truncationMode = default, string id = default, string @object = default, ResponseStatus? status = default, DateTimeOffset createdAt = default, ResponseError error = default, ResponseIncompleteStatusDetails incompleteStatusDetails = default, IEnumerable outputItems = default, ResponseTokenUsage usage = default, bool parallelToolCallsEnabled = default) { metadata ??= new ChangeTrackingDictionary(); tools ??= new ChangeTrackingList(); @@ -642,7 +642,7 @@ public static OpenAIResponse OpenAIResponse(IDictionary metadata previousResponseId, model, reasoningOptions, - background, + backgroundModeEnabled, maxOutputTokenCount, instructions, textOptions, diff --git a/tests/Responses/ResponsesTests.cs b/tests/Responses/ResponsesTests.cs index e35036397..cfd028874 100644 --- a/tests/Responses/ResponsesTests.cs +++ b/tests/Responses/ResponsesTests.cs @@ -875,47 +875,64 @@ ResponseToolChoice toolChoice } [Test] - public async Task CanUseStreamingBackgroundResponses() + public async Task CanStreamBackgroundResponses() { OpenAIResponseClient client = GetTestClient("gpt-4.1-mini"); + ResponseCreationOptions options = new() + { + BackgroundModeEnabled = true, + }; + + AsyncCollectionResult updates = client.CreateResponseStreamingAsync("Hello, model!", options); + string queuedResponseId = null; + int lastSequenceNumber = 0; - await foreach (StreamingResponseUpdate update - in client.CreateResponseStreamingAsync( - "Hello, model!", - new ResponseCreationOptions() - { - Background = true, - })) + await foreach (StreamingResponseUpdate update in updates) { if (update is StreamingResponseQueuedUpdate queuedUpdate) { + // Confirm that the response has been queued and break. queuedResponseId = queuedUpdate.Response.Id; + lastSequenceNumber = queuedUpdate.SequenceNumber; break; } } Assert.That(queuedResponseId, Is.Not.Null.And.Not.Empty); + Assert.That(lastSequenceNumber, Is.GreaterThan(0)); + // Try getting the response without streaming it. OpenAIResponse retrievedResponse = await client.GetResponseAsync(queuedResponseId); - Assert.That(retrievedResponse?.Id, Is.EqualTo(queuedResponseId)); - OpenAIResponse finalStreamedResponse = null; + Assert.That(retrievedResponse, Is.Not.Null); + Assert.That(retrievedResponse.Id, Is.EqualTo(queuedResponseId)); + Assert.That(retrievedResponse.BackgroundModeEnabled, Is.True); + Assert.That(retrievedResponse.Status, Is.EqualTo(ResponseStatus.Queued)); - await foreach (StreamingResponseUpdate update - in client.GetResponseStreamingAsync(queuedResponseId, startingAfter: 2)) + // Now try continuing the stream. + AsyncCollectionResult continuedUpdates = client.GetResponseStreamingAsync(queuedResponseId, startingAfter: lastSequenceNumber); + + OpenAIResponse completedResponse = null; + int? firstContinuedSequenceNumber = null; + + await foreach (StreamingResponseUpdate update in continuedUpdates) { - Assert.That(update.SequenceNumber, Is.GreaterThan(2)); + if (firstContinuedSequenceNumber is null) + { + firstContinuedSequenceNumber = update.SequenceNumber; + } if (update is StreamingResponseCompletedUpdate completedUpdate) { - finalStreamedResponse = completedUpdate.Response; + completedResponse = completedUpdate.Response; } } - Assert.That(finalStreamedResponse?.Id, Is.EqualTo(queuedResponseId)); - Assert.That(finalStreamedResponse?.OutputItems?.FirstOrDefault(), Is.Not.Null); + Assert.That(firstContinuedSequenceNumber, Is.EqualTo(lastSequenceNumber + 1)); + Assert.That(completedResponse?.Id, Is.EqualTo(queuedResponseId)); + Assert.That(completedResponse?.OutputItems?.FirstOrDefault(), Is.Not.Null); } [Test] @@ -923,14 +940,17 @@ public async Task CanCancelBackgroundResponses() { OpenAIResponseClient client = GetTestClient("gpt-4.1-mini"); - OpenAIResponse response = await client.CreateResponseAsync( - "Hello, model!", - new ResponseCreationOptions() - { - Background = true, - }); - Assert.That(response?.Id, Is.Not.Null.And.Not.Empty); - Assert.That(response?.Status, Is.EqualTo(ResponseStatus.Queued)); + ResponseCreationOptions options = new() + { + BackgroundModeEnabled = true, + }; + + OpenAIResponse response = await client.CreateResponseAsync("Hello, model!", options); + + Assert.That(response, Is.Not.Null); + Assert.That(response.Id, Is.Not.Null.And.Not.Empty); + Assert.That(response.BackgroundModeEnabled, Is.True); + Assert.That(response.Status, Is.EqualTo(ResponseStatus.Queued)); OpenAIResponse cancelledResponse = await client.CancelResponseAsync(response.Id); Assert.That(cancelledResponse.Id, Is.EqualTo(response.Id));