Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/Custom/Responses/Items/ReasoningResponseItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace OpenAI.Responses;
Expand All @@ -12,7 +11,7 @@ public partial class ReasoningResponseItem
{
// CUSTOM: Retain optionality of OpenAPI read-only property value
[CodeGenMember("Status")]
public ReasoningStatus? Status { get; }
public ReasoningStatus? Status { get; internal set; }

// CUSTOM: Rename for collection clarity
[CodeGenMember("Summary")]
Expand Down
146 changes: 146 additions & 0 deletions src/Custom/Responses/OpenAIResponsesModelFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace OpenAI.Responses;

/// <summary> Model factory for models. </summary>
public static partial class OpenAIResponsesModelFactory
{
/// <summary> Initializes a new instance of <see cref="OpenAI.Responses.OpenAIResponse"/>. </summary>
/// <returns> A new <see cref="OpenAI.Responses.OpenAIResponse"/> instance for mocking. </returns>
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<ResponseItem> outputItems = null,
bool parallelToolCallsEnabled = default,
ResponseToolChoice toolChoice = null,
string model = null,
IDictionary<string, string> metadata = null,
float? temperature = null,
float? topP = null,
string previousResponseId = null,
bool? background = null,
string instructions = null,
IEnumerable<ResponseTool> tools = null)
{
outputItems ??= new List<ResponseItem>();
tools ??= new List<ResponseTool>();
metadata ??= new Dictionary<string, string>();

return new OpenAIResponse(
metadata: metadata,
temperature: temperature,
topP: topP,
serviceTier: null,
previousResponseId: previousResponseId,
background: background,
instructions: instructions,
tools: tools.ToList(),
id: id,
status: status,
createdAt: createdAt,
error: error,
usage: usage,
endUserId: endUserId,
reasoningOptions: reasoningOptions,
maxOutputTokenCount: maxOutputTokenCount,
textOptions: textOptions,
truncationMode: truncationMode,
incompleteStatusDetails: incompleteStatusDetails,
outputItems: outputItems.ToList(),
parallelToolCallsEnabled: parallelToolCallsEnabled,
toolChoice: toolChoice,
model: model,
@object: "response",
additionalBinaryDataProperties: null);
}

/// <summary> Initializes a new instance of <see cref="OpenAI.Responses.MessageResponseItem"/>. </summary>
/// <returns> A new <see cref="OpenAI.Responses.MessageResponseItem"/> instance for mocking. </returns>
public static MessageResponseItem MessageResponseItem(
string id = null,
MessageRole role = MessageRole.Assistant,
MessageStatus? status = null)
{
// Convert the public MessageRole to the internal role type
InternalResponsesMessageRole internalRole = role.ToSerialString();

return new MessageResponseItem(
id: id,
internalRole: internalRole,
status: status);
}

/// <summary> Initializes a new instance of <see cref="OpenAI.Responses.ReasoningResponseItem"/>. </summary>
/// <param name="id">The ID of the reasoning response item.</param>
/// <param name="encryptedContent">The encrypted reasoning content.</param>
/// <param name="status">The status of the reasoning response item.</param>
/// <param name="summaryParts">The collection of summary parts.</param>
/// <returns> A new <see cref="OpenAI.Responses.ReasoningResponseItem"/> instance for mocking. </returns>
public static ReasoningResponseItem ReasoningResponseItem(
string id = null,
string encryptedContent = null,
ReasoningStatus? status = null,
IEnumerable<ReasoningSummaryPart> summaryParts = null)
{
summaryParts ??= new List<ReasoningSummaryPart>();

var item = new ReasoningResponseItem(
kind: InternalItemType.Reasoning,
id: id,
additionalBinaryDataProperties: null,
encryptedContent: encryptedContent,
summaryParts: summaryParts.ToList());

item.Status = status;
return item;
}

/// <summary> Initializes a new instance of <see cref="OpenAI.Responses.ReasoningResponseItem"/> with summary text. </summary>
/// <param name="id">The ID of the reasoning response item.</param>
/// <param name="encryptedContent">The encrypted reasoning content.</param>
/// <param name="status">The status of the reasoning response item.</param>
/// <param name="summaryText">The summary text to create a ReasoningSummaryTextPart from.</param>
/// <returns> A new <see cref="OpenAI.Responses.ReasoningResponseItem"/> instance for mocking. </returns>
public static ReasoningResponseItem ReasoningResponseItem(
string id = null,
string encryptedContent = null,
ReasoningStatus? status = null,
string summaryText = null)
{
var summaryParts = !string.IsNullOrEmpty(summaryText)
? new List<ReasoningSummaryPart> { new ReasoningSummaryTextPart(summaryText) }
: new List<ReasoningSummaryPart>();

var item = new ReasoningResponseItem(
kind: InternalItemType.Reasoning,
id: id,
additionalBinaryDataProperties: null,
encryptedContent: encryptedContent,
summaryParts: summaryParts);

item.Status = status;
return item;
}

/// <summary> Initializes a new instance of <see cref="OpenAI.Responses.ReferenceResponseItem"/>. </summary>
/// <returns> A new <see cref="OpenAI.Responses.ReferenceResponseItem"/> instance for mocking. </returns>
public static ReferenceResponseItem ReferenceResponseItem(
string id = null)
{
return new ReferenceResponseItem(
kind: InternalItemType.ItemReference,
id: id,
additionalBinaryDataProperties: null);
}
}
106 changes: 106 additions & 0 deletions tests/Responses/OpenAIResponsesModelFactoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using OpenAI.Responses;

namespace OpenAI.Tests.Responses;

[Parallelizable(ParallelScope.All)]
[Category("Responses")]
[Category("Smoke")]
public partial class OpenAIResponsesModelFactoryTests
{
[Test]
public void OpenAIResponseWorks()
{
string id = "response_123";
DateTimeOffset createdAt = DateTimeOffset.UtcNow;
ResponseStatus status = ResponseStatus.Completed;
string model = "gpt-4o";
IEnumerable<ResponseItem> outputItems = [
OpenAIResponsesModelFactory.MessageResponseItem(id: "msg_1", role: MessageRole.User, status: MessageStatus.Completed),
OpenAIResponsesModelFactory.ReasoningResponseItem(id: "reason_1", encryptedContent: "encrypted", status: ReasoningStatus.InProgress, summaryText: "summary")
];

OpenAIResponse response = OpenAIResponsesModelFactory.OpenAIResponse(
id: id,
createdAt: createdAt,
status: status,
model: model,
outputItems: outputItems);

Assert.That(response.Id, Is.EqualTo(id));
Assert.That(response.CreatedAt, Is.EqualTo(createdAt));
Assert.That(response.Status, Is.EqualTo(status));
Assert.That(response.Model, Is.EqualTo(model));
Assert.That(response.OutputItems.SequenceEqual(outputItems), Is.True);
}

[Test]
public void MessageResponseItemWorks()
{
string id = "message_123";
MessageRole role = MessageRole.Developer;
MessageStatus status = MessageStatus.InProgress;

MessageResponseItem messageItem = OpenAIResponsesModelFactory.MessageResponseItem(
id: id,
role: role,
status: status);

Assert.That(messageItem.Id, Is.EqualTo(id));
Assert.That(messageItem.Role, Is.EqualTo(role));
Assert.That(messageItem.Status, Is.EqualTo(status));
}

[Test]
public void ReasoningResponseItemWorks()
{
string id = "reasoning_123";
string encryptedContent = "encrypted_reasoning_data";
ReasoningStatus status = ReasoningStatus.Completed;
var summaryParts = new List<ReasoningSummaryPart> { new ReasoningSummaryTextPart("test summary") };

ReasoningResponseItem reasoningItem = OpenAIResponsesModelFactory.ReasoningResponseItem(
id: id,
encryptedContent: encryptedContent,
status: status,
summaryParts: summaryParts);

Assert.That(reasoningItem.Id, Is.EqualTo(id));
Assert.That(reasoningItem.EncryptedContent, Is.EqualTo(encryptedContent));
Assert.That(reasoningItem.Status, Is.EqualTo(status));
Assert.That(reasoningItem.SummaryParts.SequenceEqual(summaryParts), Is.True);
}

[Test]
public void ReasoningResponseItemWithSummaryTextWorks()
{
string id = "reasoning_456";
string encryptedContent = "encrypted_data";
ReasoningStatus status = ReasoningStatus.InProgress;
string summaryText = "This is a reasoning summary";

ReasoningResponseItem reasoningItem = OpenAIResponsesModelFactory.ReasoningResponseItem(
id: id,
encryptedContent: encryptedContent,
status: status,
summaryText: summaryText);

Assert.That(reasoningItem.Id, Is.EqualTo(id));
Assert.That(reasoningItem.EncryptedContent, Is.EqualTo(encryptedContent));
Assert.That(reasoningItem.Status, Is.EqualTo(status));
Assert.That(reasoningItem.GetSummaryText(), Is.EqualTo(summaryText));
}

[Test]
public void ReferenceResponseItemWorks()
{
string id = "reference_123";

ReferenceResponseItem referenceItem = OpenAIResponsesModelFactory.ReferenceResponseItem(id: id);

Assert.That(referenceItem.Id, Is.EqualTo(id));
}
}