Sitelet https://github.com/openai/openai-dotnet/commit/06c6fe079620b1290179bb03d60180bf6cfc4bd7
Skip to content

Commit 06c6fe0

Browse files
authored
Prepare 2.9.0 release (#986)
1 parent e615290 commit 06c6fe0

7 files changed

Lines changed: 193 additions & 17 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,177 @@
11
# Release History
22

3+
## 2.9.0 (2026-02-27)
4+
5+
### Acknowledgments
6+
7+
Thank you to our developer community members who helped to make the OpenAI client library better with their contributions to this release:
8+
9+
- [@mokarchi](https://github.com/mokarchi)
10+
- [@alty-ir](https://github.com/alty-ir)
11+
- [@peibekwe](https://github.com/peibekwe)
12+
- [@crickman](https://github.com/crickman)
13+
- [@jpaarhuis](https://github.com/jpaarhuis)
14+
- [@salmanmkc](https://github.com/salmanmkc)
15+
16+
### Features Added
17+
18+
- OpenAI.Audio:
19+
- Added support for `AudioClient` configuration and dependency injection via the new `AudioClientSettings` class.
20+
- OpenAI.Batch:
21+
- Added support for `BatchClient` configuration and dependency injection via the new `BatchClientSettings` class.
22+
- OpenAI.Chat:
23+
- Added support for `ChatClient` configuration and dependency injection via the new `ChatClientSettings` class.
24+
- Added value of `None` to `ChatReasoningEffortLevel` enum to allow opting out of reasoning.
25+
- OpenAI.Containers:
26+
- Added support for `ContainerClient` configuration and dependency injection via the new `ContainerClientSettings` class.
27+
- OpenAI.Conversations:
28+
- Added support for `ConversationClient` configuration and dependency injection via the new `ConversationClientSettings` class.
29+
- OpenAI.Embeddings:
30+
- Added support for `EmbeddingClient` configuration and dependency injection via the new `EmbeddingClientSettings` class.
31+
- OpenAI.Evals:
32+
- Added support for `EvaluationClient` configuration and dependency injection via the new `EvaluationClientSettings` class.
33+
- OpenAI.Files:
34+
- Added support for `OpenAIFileClient` configuration and dependency injection via the new `OpenAIFileClientSettings` class.
35+
- Added support for retrieving files using pagination via new overloads of the `GetFiles` and `GetFilesAsync` methods in the `OpenAIFileClient`.
36+
- OpenAI.FineTuning:
37+
- Added support for `FineTuningClient` configuration and dependency injection via the new `FineTuningClientSettings` class.
38+
- OpenAI.Graders:
39+
- Added support for `GraderClient` configuration and dependency injection via the new `GraderClientSettings` class.
40+
- OpenAI.Images:
41+
- Added support for `ImageClient` configuration and dependency injection via the new `ImageClientSettings` class.
42+
- Added value of `HighQuality` to `GeneratedImageQuality` enum to allow generating higher quality images.
43+
- Added `InputFidelity` property to `ImageEditOptions` to control how closely distinctive features from the input are preserved.
44+
- Added `OutputCompressionFactor` property to `ImageEditOptions` to set the compression level (0-100%) for `jpeg` or `webp` outputs.
45+
- Added `OutputFileFormat` property to `ImageEditOptions` to set the file format in which the generated images are returned.
46+
- Added `Background` property to `GeneratedImageCollection`.
47+
- Added `OutputFileFormat` property to `GeneratedImageCollection`.
48+
- Added `Quality` property to `GeneratedImageCollection`.
49+
- Added `Size` property to `GeneratedImageCollection`.
50+
- OpenAI.Models:
51+
- Added support for `OpenAIModelClient` configuration and dependency injection via the new `OpenAIModelClientSettings` class.
52+
- OpenAI.Moderations:
53+
- Added support for `ModerationClient` configuration and dependency injection via the new `ModerationClientSettings` class.
54+
- Added support for classifying multi-modal inputs via new `ClassifyInputs` and `ClassifyInputsAsync` methods in the `ModerationClient`.
55+
- Use the new `ModerationInputPart` class to create text or image inputs for classication.
56+
- Use the new `ApplicableInputKinds` property of the `ModerationCategory` class to understand to which parts of the input the moderation results apply.
57+
- OpenAI.Realtime:
58+
- Added support for the stable version of the Realtime REST API.
59+
- Added support for `RealtimeClient` configuration and dependency injection via the new `RealtimeClientSettings` class.
60+
- Added support for integrating with remote MCP servers.
61+
- Users can add the new `RealtimeMcpTool` to the `Tools` property of their `RealtimeConversationSessionOptions` and configure it.
62+
- Use the `AllowedTools` property to limit which of the server tools can be called by the model.
63+
- Use the `ToolCallApprovalPolicy` property to specify which tools require an explicit approval before being called by the model.
64+
- Use the `AuthorizationToken` property to specify the access token to used when authenticating with the remote MCP server.
65+
- Use the `ConnectorId` property to use the OpenAI-maintained MCP wrappers for popular services like Microsoft Outlook or Dropbox.
66+
- Added a new `RealtimeClientCommand` class that represents client events to be used with the new `SendCommand` and `SendCommandAsync` overloads in the `RealtimeSessionClient` and exposed all supported client events as derived types:
67+
- `RealtimeClientCommandConversationItemCreate`
68+
- `RealtimeClientCommandConversationItemDelete`
69+
- `RealtimeClientCommandConversationItemRetrieve`
70+
- `RealtimeClientCommandConversationItemTruncate`
71+
- `RealtimeClientCommandInputAudioBufferAppend`
72+
- `RealtimeClientCommandInputAudioBufferClear`
73+
- `RealtimeClientCommandInputAudioBufferCommit`
74+
- `RealtimeClientCommandOutputAudioBufferClear`
75+
- `RealtimeClientCommandResponseCancel`
76+
- `RealtimeClientCommandResponseCreate`
77+
- `RealtimeClientCommandSessionUpdate`
78+
- Added support for System.Client.Model's `JsonPatch`, which enables users to get and set additional JSON properties in response and request payloads.
79+
- OpenAI.Responses:
80+
- Added support for `ResponsesClient` configuration and dependency injection via the new `ResponsesClientSettings` class.
81+
- Added support for compacting conversations via the new `CompactResponse` and `CompactResponseAsync` protocol methods in the `ResponsesClient`.
82+
- Added support for returning the number of input tokens that a Response would consume via the new `GetInputTokenCount` and `GetInputTokenCountAsync` protocol methods in the `ResponsesClient`.
83+
- Added value of `None` to `ResponseReasoningEffortLevel` enum to allow opting out of reasoning.
84+
- Added `InputImageUri` property to `ResponseContentPart` to manage image inputs as URIs.
85+
- Added implicit conversion operators to `McpToolCallApprovalPolicy` to facilitate its assignment.
86+
- OpenAI.VectorStores:
87+
- Added support for `VectorStoreClient` configuration and dependency injection via the new `VectorStoreClientSettings` class.
88+
- OpenAI.Videos:
89+
- Added support for `VideoClient` configuration and dependency injection via the new `VideoClientSettings` class.
90+
91+
### Bugs Fixed
92+
93+
- OpenAI.Chat:
94+
- Fixed a concurrency issue corrupting the state of the `ChatCompletionOptions` argument when the same instance was passed into concurrent calls of `CompleteChat`/`CompleteChatAsync` and/or `CompleteChatStreaming`/`CompleteChatStreamingAsync`.
95+
- OpenAI.Realtime:
96+
- Fixed an issue causing permanent state corruption when sending audio was cancelled in `RealtimeSessionClient`.
97+
- Fixed an issue with `RealtimeSessionClient` always requiring an API key.
98+
- OpenAI.Responses:
99+
- Fixed a concurrency issue corrupting the state of the `CreateResponseOptions` argument when the same instance was passed into concurrent calls of `CreateResponse`/`CreateResponseAsync` and/or `CreateResponseStreaming`/`CreateResponseStreamingAsync`.
100+
101+
### Other Changes
102+
103+
- Updated the `System.ClientModel` dependency to version 1.9.0. For more information, see the [System.ClientModel changelog](https://github.com/Azure/azure-sdk-for-net/blob/System.ClientModel_1.9.0/sdk/core/System.ClientModel/CHANGELOG.md).
104+
105+
### Breaking Changes in Preview APIs
106+
107+
- OpenAI.Images:
108+
- Changed the type of the `InputTokenCount`, `OutputTokenCount`, and `TotalTokenCount` properties of `ImageTokenUsage` from `int` to `long`.
109+
- OpenAI.Realtime:
110+
- This release migrates the implementation of the Realtime API from the beta REST API to the GA REST API. As such, it contains numerous breaking changes, including the following:
111+
- Renamed `RealtimeSession` to `RealtimeSessionClient`.
112+
- Renamed `ConversationTool` to `RealtimeTool` and exposed all supported tools as derived types:
113+
- `RealtimeFunctionTool`
114+
- `RealtimeMcpTool`
115+
- Changed `RealtimeItem` into a class hierarchy and exposed all supported item types as derived types:
116+
- `RealtimeMessageItem`
117+
- `RealtimeFunctionCallItem`
118+
- `RealtimeFunctionCallOutputItem`
119+
- `RealtimeMcpToolCallItem`
120+
- `RealtimeMcpToolDefinitionListItem`
121+
- `RealtimeMcpToolCallApprovalRequestItem`
122+
- `RealtimeMcpToolCallApprovalResponseItem`
123+
- Renamed `RealtimeUpdate` to `RealtimeServerUpdate` and exposed all supported server events as derived types:
124+
- `RealtimeServerUpdateConversationCreated`
125+
- `RealtimeServerUpdateConversationItemAdded`
126+
- `RealtimeServerUpdateConversationItemCreated`
127+
- `RealtimeServerUpdateConversationItemDeleted`
128+
- `RealtimeServerUpdateConversationItemDone`
129+
- `RealtimeServerUpdateConversationItemInputAudioTranscriptionCompleted`
130+
- `RealtimeServerUpdateConversationItemInputAudioTranscriptionDelta`
131+
- `RealtimeServerUpdateConversationItemInputAudioTranscriptionFailed`
132+
- `RealtimeServerUpdateConversationItemInputAudioTranscriptionSegment`
133+
- `RealtimeServerUpdateConversationItemRetrieved`
134+
- `RealtimeServerUpdateConversationItemTruncated`
135+
- `RealtimeServerUpdateError`
136+
- `RealtimeServerUpdateInputAudioBufferCleared`
137+
- `RealtimeServerUpdateInputAudioBufferCommitted`
138+
- `RealtimeServerUpdateInputAudioBufferDtmfEventReceived`
139+
- `RealtimeServerUpdateInputAudioBufferSpeechStarted`
140+
- `RealtimeServerUpdateInputAudioBufferSpeechStopped`
141+
- `RealtimeServerUpdateInputAudioBufferTimeoutTriggered`
142+
- `RealtimeServerUpdateMcpListToolsCompleted`
143+
- `RealtimeServerUpdateMcpListToolsFailed`
144+
- `RealtimeServerUpdateMcpListToolsInProgress`
145+
- `RealtimeServerUpdateOutputAudioBufferCleared`
146+
- `RealtimeServerUpdateOutputAudioBufferStarted`
147+
- `RealtimeServerUpdateOutputAudioBufferStopped`
148+
- `RealtimeServerUpdateRateLimitsUpdated`
149+
- `RealtimeServerUpdateResponseContentPartAdded`
150+
- `RealtimeServerUpdateResponseContentPartDone`
151+
- `RealtimeServerUpdateResponseCreated`
152+
- `RealtimeServerUpdateResponseDone`
153+
- `RealtimeServerUpdateResponseFunctionCallArgumentsDelta`
154+
- `RealtimeServerUpdateResponseFunctionCallArgumentsDone`
155+
- `RealtimeServerUpdateResponseMcpCallArgumentsDelta`
156+
- `RealtimeServerUpdateResponseMcpCallArgumentsDone`
157+
- `RealtimeServerUpdateResponseMcpCallCompleted`
158+
- `RealtimeServerUpdateResponseMcpCallFailed`
159+
- `RealtimeServerUpdateResponseMcpCallInProgress`
160+
- `RealtimeServerUpdateResponseOutputAudioDelta`
161+
- `RealtimeServerUpdateResponseOutputAudioDone`
162+
- `RealtimeServerUpdateResponseOutputAudioTranscriptDelta`
163+
- `RealtimeServerUpdateResponseOutputAudioTranscriptDone`
164+
- `RealtimeServerUpdateResponseOutputItemAdded`
165+
- `RealtimeServerUpdateResponseOutputItemDone`
166+
- `RealtimeServerUpdateResponseOutputTextDelta`
167+
- `RealtimeServerUpdateResponseOutputTextDone`
168+
- `RealtimeServerUpdateSessionCreated`
169+
- `RealtimeServerUpdateSessionUpdated`
170+
- We recommend checking out our [examples](https://github.com/openai/openai-dotnet/tree/main/examples/Realtime) and tests as well as the [migration guide](https://developers.openai.com/api/docs/guides/realtime/#beta-to-ga-migration) for tips on how to use the new API surface.
171+
- OpenAI.Responses:
172+
- Removed the `Model` property of the `ResponsesClient` in favor of specifying the model on a per-call basis when calling `CreateResponse`/`CreateResponseAsync` or `CreateResponseStreaming`/`CreateResponseStreamingAsync`. To do this, set the `Model` property of the `CreateResponseOptions` parameter. With this change, users no longer have to provide a model unless it is actually needed.
173+
- Changed the type of the `Instructions` property of `ResponseResult` from `string` to `IList<ResponseItem>` to handle multi-item instructions.
174+
3175
## 2.8.0 (2025-12-11)
4176

5177
### Features Added

‎Directory.Build.props‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
<!-- Versioning -->
4949
<PropertyGroup>
50-
<VersionPrefix>2.8.0</VersionPrefix>
50+
<VersionPrefix>2.9.0</VersionPrefix>
5151
<VersionSuffix></VersionSuffix>
5252
<InformationalVersion>$(Version)</InformationalVersion>
5353
</PropertyGroup>

‎scripts/Test-ApiCompatibility.ps1‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ function Invoke-APICompat {
6969
[Parameter(Mandatory = $true)]
7070
[string]$ProjectPath,
7171

72+
[Parameter(Mandatory = $true)]
73+
[string]$DirectoryBuildPropsPath,
74+
7275
[Parameter(Mandatory = $true)]
7376
[string]$ReleasePath,
7477

@@ -89,9 +92,9 @@ function Invoke-APICompat {
8992
Invoke-DotNetPack -ProjectPath $ProjectPath
9093

9194
# Extract the values of VersionPrefix and VersionSuffix from the .csproj XML file.
92-
$xml = [xml](Get-Content $ProjectPath)
93-
$versionPrefix = $($xml.Project.PropertyGroup[0].VersionPrefix)
94-
$versionSuffix = $($xml.Project.PropertyGroup[0].VersionSuffix)
95+
$xml = [xml](Get-Content $DirectoryBuildPropsPath)
96+
$versionPrefix = $($xml.Project.PropertyGroup[3].VersionPrefix)
97+
$versionSuffix = $($xml.Project.PropertyGroup[3].VersionSuffix)
9598
$currentVersion = [string]::IsNullOrEmpty($versionSuffix) ? "$($versionPrefix)" : "$($versionPrefix)-$($versionSuffix)"
9699

97100
$currentNuGetPackagePath = Join-Path $ReleasePath "$($PackageName).$($currentVersion).nupkg"
@@ -160,6 +163,7 @@ function Invoke-APICompat {
160163

161164
$repoRootPath = Join-Path $PSScriptRoot .. -Resolve
162165
$projectPath = Join-Path $repoRootPath "src\OpenAI.csproj"
166+
$buildPropsPath = Join-Path $repoRootPath "Directory.Build.props"
163167
$releasePath = Join-Path $repoRootPath "src\bin\Release"
164168

165169
$experimentalNamespaces = @(
@@ -175,7 +179,8 @@ $experimentalNamespaces = @(
175179
)
176180

177181
Invoke-APICompat -ProjectPath $projectPath `
182+
-DirectoryBuildPropsPath $buildPropsPath `
178183
-ReleasePath $releasePath `
179184
-PackageName "OpenAI" `
180-
-BaselineVersion "2.7.0" `
185+
-BaselineVersion "2.8.0" `
181186
-IgnoredNamespaces $experimentalNamespaces

‎tests/Assistants/AssistantsTests.cs‎

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -412,15 +412,12 @@ public async Task BasicRunStepFunctionalityWorks()
412412
Assert.That(details?.CreatedMessageId, Is.Not.Null.And.Not.Empty);
413413

414414
details = secondStep.Details;
415-
Assert.Multiple(() =>
416-
{
417-
Assert.That(details?.ToolCalls.Count, Is.GreaterThan(0));
418-
Assert.That(details.ToolCalls[0].Kind, Is.EqualTo(RunStepToolCallKind.CodeInterpreter));
419-
Assert.That(details.ToolCalls[0].Id, Is.Not.Null.And.Not.Empty);
420-
Assert.That(details.ToolCalls[0].CodeInterpreterInput, Is.Not.Null.And.Not.Empty);
421-
Assert.That(details.ToolCalls[0].CodeInterpreterOutputs?.Count, Is.GreaterThan(0));
422-
Assert.That(details.ToolCalls[0].CodeInterpreterOutputs[0].ImageFileId, Is.Not.Null.And.Not.Empty);
423-
});
415+
Assert.That(details?.ToolCalls.Count, Is.GreaterThan(0));
416+
Assert.That(details.ToolCalls[0].Kind, Is.EqualTo(RunStepToolCallKind.CodeInterpreter));
417+
Assert.That(details.ToolCalls[0].Id, Is.Not.Null.And.Not.Empty);
418+
Assert.That(details.ToolCalls[0].CodeInterpreterInput, Is.Not.Null.And.Not.Empty);
419+
Assert.That(details.ToolCalls[0].CodeInterpreterOutputs?.Count, Is.GreaterThan(0));
420+
Assert.That(details.ToolCalls[0].CodeInterpreterOutputs[0].ImageFileId, Is.Not.Null.And.Not.Empty);
424421
}
425422

426423
[RecordedTest]

‎tests/Audio/TranscriptionTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public async Task StreamingTranscriptionWorks(AudioSourceKind audioSourceKind)
303303
}
304304
}
305305

306-
Assert.That(deltaBuilder.ToString().ToLower(), Does.Contain("hello world"));
306+
Assert.That(deltaBuilder.ToString().ToLower(), Does.Contain("this is a test"));
307307

308308
inputStream?.Dispose();
309309
}

‎tests/ClientTests.cs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using NUnit.Framework;
2+
using OpenAI.Realtime;
23
using System;
34
using System.ClientModel;
45
using System.ClientModel.Primitives;
@@ -24,7 +25,8 @@ public static IEnumerable<Type> GetClientTypes()
2425
type.IsClass &&
2526
!type.IsAbstract &&
2627
type.Name.EndsWith("Client", StringComparison.Ordinal) &&
27-
HasEndpointField(type))
28+
HasEndpointField(type) &&
29+
type != typeof(RealtimeSessionClient))
2830
.OrderBy(type => type.Name); // For consistent ordering in test results
2931
}
3032

‎tests/Files/Files.UploadsTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public async Task CreateUploadWorks(bool useTopLevelClient)
2525
// are setting the internal Uploads client correctly.
2626

2727
OpenAIFileClient fileClient = useTopLevelClient
28-
? TestEnvironment.GetTestClient<OpenAIClient>().GetOpenAIFileClient()
28+
? GetProxiedOpenAIClient<OpenAIClient>().GetOpenAIFileClient()
2929
: GetProxiedOpenAIClient<OpenAIFileClient>();
3030
BinaryContent content = BinaryContent.Create(BinaryData.FromObjectAsJson(new
3131
{

0 commit comments

Comments
 (0)