Skip to content

Commit 69d869c

Browse files
authored
Prepare 2.7.0 release (#834)
1 parent cadcd38 commit 69d869c

16 files changed

+1273
-725
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release History
22

3-
## 2.7.0 (Unreleased)
3+
## 2.7.0 (2025-11-13)
44

55
### Acknowledgments
66

api/OpenAI.net8.0.cs

Lines changed: 67 additions & 0 deletions
Large diffs are not rendered by default.

api/OpenAI.netstandard2.0.cs

Lines changed: 67 additions & 0 deletions
Large diffs are not rendered by default.

scripts/Test-ApiCompatibility.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,5 @@ $experimentalNamespaces = @(
177177
Invoke-APICompat -ProjectPath $projectPath `
178178
-ReleasePath $releasePath `
179179
-PackageName "OpenAI" `
180-
-BaselineVersion "2.5.0" `
180+
-BaselineVersion "2.6.0" `
181181
-IgnoredNamespaces $experimentalNamespaces

src/OpenAI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<PackageLicenseExpression>MIT</PackageLicenseExpression>
99
<Copyright>Copyright (c) 2024 OpenAI (https://openai.com)</Copyright>
1010

11-
<VersionPrefix>2.6.0</VersionPrefix>
11+
<VersionPrefix>2.7.0</VersionPrefix>
1212
<VersionSuffix></VersionSuffix>
1313

1414
<TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>

tests/Assistants/Assistants.VectorStoresTests.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ public async Task CanCreateGetAndDeleteVectorStores()
108108
public async Task CanEnumerateVectorStores()
109109
{
110110
VectorStoreClient client = GetTestClient();
111-
for (int i = 0; i < 5; i++)
111+
112+
int vectorStoreCount = 3;
113+
114+
for (int i = 0; i < vectorStoreCount; i++)
112115
{
113116
VectorStore vectorStore = await client.CreateVectorStoreAsync(
114117
new VectorStoreCreationOptions()
@@ -122,7 +125,7 @@ public async Task CanEnumerateVectorStores()
122125

123126
if (Mode != RecordedTestMode.Playback)
124127
{
125-
await Task.Delay(5000);
128+
await Task.Delay(TimeSpan.FromSeconds(10));
126129
}
127130

128131
int lastIdSeen = int.MaxValue;
@@ -155,7 +158,9 @@ public async Task CanAssociateFiles()
155158
VectorStore vectorStore = await client.CreateVectorStoreAsync();
156159
Validate(vectorStore);
157160

158-
IReadOnlyList<OpenAIFile> files = await GetNewTestFiles(3);
161+
int fileCount = 3;
162+
163+
IReadOnlyList<OpenAIFile> files = await GetNewTestFiles(fileCount);
159164

160165
foreach (OpenAIFile file in files)
161166
{
@@ -170,6 +175,10 @@ public async Task CanAssociateFiles()
170175
Assert.That(vectorStoreFile.Status, Is.EqualTo(VectorStoreFileStatus.InProgress));
171176
});
172177
}
178+
if (Mode != RecordedTestMode.Playback)
179+
{
180+
await Task.Delay(TimeSpan.FromSeconds(10));
181+
}
173182

174183
FileFromStoreRemovalResult removalResult = await client.RemoveFileFromVectorStoreAsync(vectorStore.Id, files[0].Id);
175184
Assert.That(removalResult.FileId, Is.EqualTo(files[0].Id));
@@ -189,7 +198,7 @@ public async Task CanAssociateFiles()
189198
Assert.That(vectorStoreFile.FileId, Is.Not.EqualTo(files[0].Id));
190199
Assert.That(vectorStoreFile.VectorStoreId, Is.EqualTo(vectorStore.Id));
191200
}
192-
Assert.That(count, Is.EqualTo(2));
201+
Assert.That(count, Is.EqualTo(fileCount - 1));
193202
}
194203

195204
[RecordedTest]

tests/Assistants/AssistantsTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,11 @@ public async Task Pagination_CanEnumerateAssistantsAsync()
10031003
Assert.That(assistant.Name, Is.EqualTo($"Test Assistant {i}"));
10041004
}
10051005

1006+
if (Mode != RecordedTestMode.Playback)
1007+
{
1008+
await Task.Delay(TimeSpan.FromSeconds(10));
1009+
}
1010+
10061011
// Page through collection
10071012
int count = 0;
10081013
AsyncCollectionResult<Assistant> assistants = client.GetAssistantsAsync(new AssistantCollectionOptions() { Order = AssistantCollectionOrder.Descending });
@@ -1031,7 +1036,7 @@ public async Task Pagination_CanEnumerateAssistantsAsync()
10311036
[RecordedTest]
10321037
public async Task Pagination_CanPageThroughAssistantCollection()
10331038
{
1034-
const int TestAssistantCount = 10;
1039+
const int TestAssistantCount = 5;
10351040
const int TestPageSizeLimit = 2;
10361041

10371042
AssistantClient client = GetTestClient();
@@ -1047,6 +1052,11 @@ public async Task Pagination_CanPageThroughAssistantCollection()
10471052
Assert.That(assistant.Name, Is.EqualTo($"Test Assistant {i}"));
10481053
}
10491054

1055+
if (Mode != RecordedTestMode.Playback)
1056+
{
1057+
await Task.Delay(TimeSpan.FromSeconds(10));
1058+
}
1059+
10501060
// Page through collection
10511061
int count = 0;
10521062
int pageCount = 0;
@@ -1096,7 +1106,7 @@ private static IEnumerable<Assistant> GetAssistantsFromPage(ClientResult page)
10961106
[RecordedTest]
10971107
public async Task Pagination_CanRehydrateAssistantPageCollectionFromBytes()
10981108
{
1099-
const int TestAssistantCount = 10;
1109+
const int TestAssistantCount = 5;
11001110
const int TestPageSizeLimit = 2;
11011111

11021112
AssistantClient client = GetTestClient();
@@ -1112,6 +1122,11 @@ public async Task Pagination_CanRehydrateAssistantPageCollectionFromBytes()
11121122
Assert.That(assistant.Name, Is.EqualTo($"Test Assistant {i}"));
11131123
}
11141124

1125+
if (Mode != RecordedTestMode.Playback)
1126+
{
1127+
await Task.Delay(TimeSpan.FromSeconds(10));
1128+
}
1129+
11151130
AsyncCollectionResult<Assistant> assistants = client.GetAssistantsAsync(
11161131
new AssistantCollectionOptions()
11171132
{

tests/Responses/ResponsesToolTests.cs

Lines changed: 73 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -810,26 +810,38 @@ in client.CreateResponseStreamingAsync(message, responseOptions))
810810
}
811811

812812
[RecordedTest]
813+
[LiveOnly(Reason = "Temp due to the recording framework timing out")]
813814
public async Task ImageGenToolInputMaskWithImageBytes()
814815
{
815-
OpenAIResponseClient client = GetTestClient();
816+
OpenAIResponseClient client = GetTestClient(options: new() { NetworkTimeout = TimeSpan.FromMinutes(5) });
816817

817-
string imageFilename = "images_dog_and_cat.png";
818+
string imageFilename = "images_empty_room.png";
818819
string imagePath = Path.Combine("Assets", imageFilename);
820+
BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath));
821+
822+
string maskFilename = "images_empty_room_with_mask.png";
823+
string maskPath = Path.Combine("Assets", maskFilename);
824+
BinaryData maskBytes = BinaryData.FromBytes(File.ReadAllBytes(maskPath));
825+
826+
List<ResponseItem> inputItems = [
827+
ResponseItem.CreateUserMessageItem("Edit this image by adding a big cat with big round eyes and large cat ears, sitting in an empty room and looking at the camera."),
828+
ResponseItem.CreateUserMessageItem([ResponseContentPart.CreateInputImagePart(imageBytes, "image/png")])
829+
];
830+
819831
ResponseCreationOptions options = new()
820832
{
821833
Tools =
822834
{
823-
ResponseTool.CreateImageGenerationTool(
824-
model: "gpt-image-1",
825-
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
826-
inputImageMask: new(BinaryData.FromBytes(File.ReadAllBytes(imagePath)), "image/png"))
835+
ResponseTool.CreateImageGenerationTool(
836+
model: "gpt-image-1-mini",
837+
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
838+
size: ImageGenerationToolSize.W1024xH1024,
839+
quality: ImageGenerationToolQuality.Low,
840+
inputImageMask: new(maskBytes, "image/png"))
827841
}
828842
};
829843

830-
OpenAIResponse response = await client.CreateResponseAsync(
831-
"Generate an image of gray tabby cat hugging an otter with an orange scarf",
832-
options);
844+
OpenAIResponse response = await client.CreateResponseAsync(inputItems, options);
833845

834846
Assert.That(response.OutputItems, Has.Count.EqualTo(2));
835847
Assert.That(response.OutputItems[0], Is.InstanceOf<ImageGenerationCallResponseItem>());
@@ -849,22 +861,30 @@ public async Task ImageGenToolInputMaskWithImageBytes()
849861
[RecordedTest]
850862
public async Task ImageGenToolInputMaskWithImageUri()
851863
{
852-
OpenAIResponseClient client = GetTestClient();
864+
OpenAIResponseClient client = GetTestClient(options: new() { NetworkTimeout = TimeSpan.FromMinutes(5) });
865+
866+
Uri imageUri = new("https://github.com/openai/openai-dotnet/blob/db6328accdd7927f19915cdc5412eb841f2447c1/tests/Assets/images_empty_room.png?raw=true");
867+
Uri maskUri = new("https://github.com/openai/openai-dotnet/blob/db6328accdd7927f19915cdc5412eb841f2447c1/tests/Assets/images_empty_room_with_mask.png?raw=true");
868+
869+
List<ResponseItem> inputItems = [
870+
ResponseItem.CreateUserMessageItem("Edit this image by adding a big cat with big round eyes and large cat ears, sitting in an empty room and looking at the camera."),
871+
ResponseItem.CreateUserMessageItem([ResponseContentPart.CreateInputImagePart(imageUri)])
872+
];
853873

854874
ResponseCreationOptions options = new()
855875
{
856876
Tools =
857877
{
858-
ResponseTool.CreateImageGenerationTool(
859-
model: "gpt-image-1",
860-
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
861-
inputImageMask: new(imageUri: new Uri("https://upload.wikimedia.org/wikipedia/commons/c/c3/Openai.png")))
878+
ResponseTool.CreateImageGenerationTool(
879+
model: "gpt-image-1-mini",
880+
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
881+
size: ImageGenerationToolSize.W1024xH1024,
882+
quality: ImageGenerationToolQuality.Low,
883+
inputImageMask: new(maskUri))
862884
}
863885
};
864886

865-
OpenAIResponse response = await client.CreateResponseAsync(
866-
"Generate an image of gray tabby cat hugging an otter with an orange scarf",
867-
options);
887+
OpenAIResponse response = await client.CreateResponseAsync(inputItems, options);
868888

869889
Assert.That(response.OutputItems, Has.Count.EqualTo(2));
870890
Assert.That(response.OutputItems[0], Is.InstanceOf<ImageGenerationCallResponseItem>());
@@ -882,41 +902,59 @@ public async Task ImageGenToolInputMaskWithImageUri()
882902
}
883903

884904
[RecordedTest]
905+
[Category("MPFD")]
885906
public async Task ImageGenToolInputMaskWithFileId()
886907
{
887-
OpenAIResponseClient client = GetTestClient();
908+
OpenAIResponseClient client = GetTestClient(options: new() { NetworkTimeout = TimeSpan.FromMinutes(5) });
888909

889910
OpenAIFileClient fileClient = GetProxiedOpenAIClient<OpenAIFileClient>(TestScenario.Files);
890911

891-
string imageFilename = "images_dog_and_cat.png";
912+
string imageFilename = "images_empty_room.png";
892913
string imagePath = Path.Combine("Assets", imageFilename);
893-
using Stream image = File.OpenRead(imagePath);
894-
BinaryData imageData = BinaryData.FromStream(image);
914+
BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath));
915+
916+
string maskFilename = "images_empty_room_with_mask.png";
917+
string maskPath = Path.Combine("Assets", maskFilename);
918+
BinaryData maskBytes = BinaryData.FromBytes(File.ReadAllBytes(maskPath));
895919

896-
OpenAIFile file;
920+
OpenAIFile imageFile;
897921
using (Recording.DisableRequestBodyRecording()) // Temp pending https://github.com/Azure/azure-sdk-tools/issues/11901
898922
{
899-
file = await fileClient.UploadFileAsync(
900-
imageData,
901-
imageFilename,
902-
FileUploadPurpose.UserData);
923+
imageFile = await fileClient.UploadFileAsync(imageBytes, imageFilename, FileUploadPurpose.UserData);
924+
}
925+
Validate(imageFile);
926+
927+
OpenAIFile maskFile;
928+
using (Recording.DisableRequestBodyRecording()) // Temp pending https://github.com/Azure/azure-sdk-tools/issues/11901
929+
{
930+
maskFile = await fileClient.UploadFileAsync(maskBytes, maskFilename, FileUploadPurpose.UserData);
931+
}
932+
Validate(imageFile);
933+
934+
if (Mode != RecordedTestMode.Playback)
935+
{
936+
await Task.Delay(TimeSpan.FromSeconds(10));
903937
}
904-
Validate(file);
938+
939+
List<ResponseItem> inputItems = [
940+
ResponseItem.CreateUserMessageItem("Edit this image by adding a big cat with big round eyes and large cat ears, sitting in an empty room and looking at the camera."),
941+
ResponseItem.CreateUserMessageItem([ResponseContentPart.CreateInputImagePart(imageFileId: imageFile.Id)])
942+
];
905943

906944
ResponseCreationOptions options = new()
907945
{
908946
Tools =
909947
{
910-
ResponseTool.CreateImageGenerationTool(
911-
model: "gpt-image-1",
912-
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
913-
inputImageMask: new(fileId: file.Id))
948+
ResponseTool.CreateImageGenerationTool(
949+
model: "gpt-image-1-mini",
950+
outputFileFormat: ImageGenerationToolOutputFileFormat.Png,
951+
size: ImageGenerationToolSize.W1024xH1024,
952+
quality: ImageGenerationToolQuality.Low,
953+
inputImageMask: new(fileId: maskFile.Id))
914954
}
915955
};
916956

917-
OpenAIResponse response = await client.CreateResponseAsync(
918-
"Generate an image of gray tabby cat hugging an otter with an orange scarf",
919-
options);
957+
OpenAIResponse response = await client.CreateResponseAsync(inputItems, options);
920958

921959
Assert.That(response.OutputItems, Has.Count.EqualTo(2));
922960
Assert.That(response.OutputItems[0], Is.InstanceOf<ImageGenerationCallResponseItem>());
@@ -1003,5 +1041,5 @@ private static void ValidateCodeInterpreterEvent(ref int inProgressCount, ref in
10031041
}
10041042
}
10051043

1006-
private OpenAIResponseClient GetTestClient(string overrideModel = null) => GetProxiedOpenAIClient<OpenAIResponseClient>(TestScenario.Responses, overrideModel);
1044+
private OpenAIResponseClient GetTestClient(string overrideModel = null, OpenAIClientOptions options = null) => GetProxiedOpenAIClient<OpenAIResponseClient>(TestScenario.Responses, overrideModel, options: options);
10071045
}

0 commit comments

Comments
 (0)