Skip to content

Commit e355d4a

Browse files
authored
Merge branch 'openai:main' into addtestframework
2 parents b52c9e3 + 4709a93 commit e355d4a

File tree

323 files changed

+185046
-1636
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

323 files changed

+185046
-1636
lines changed

.github/workflows/live-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Run live tests
3333
run: dotnet test ./tests/OpenAI.Tests.csproj
3434
--configuration Release
35-
--filter="TestCategory!=Smoke&TestCategory!=Assistants&TestCategory!=Images&TestCategory!=Uploads&TestCategory!=Moderations&TestCategory!=FineTuning&TestCategory!=Conversation&TestCategory!=Manual"
35+
--filter="TestCategory!=Smoke&TestCategory!=Assistants&TestCategory!=StoredChat&TestCategory!=Images&TestCategory!=Uploads&TestCategory!=Moderations&TestCategory!=FineTuning&TestCategory!=Conversation&TestCategory!=Manual"
3636
--logger "trx;LogFilePrefix=live"
3737
--results-directory ${{github.workspace}}/artifacts/test-results
3838
${{ env.version_suffix_args}}

.github/workflows/release.yml

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
- name: Run Live Tests
5656
run: dotnet test ./tests/OpenAI.Tests.csproj
5757
--configuration Release
58-
--filter="TestCategory!=Smoke&TestCategory!=Assistants&TestCategory!=Images&TestCategory!=Uploads&TestCategory!=Moderations&TestCategory!=FineTuning&TestCategory!=Conversation&TestCategory!=Manual"
58+
--filter="TestCategory!=Smoke&TestCategory!=Assistants&TestCategory!=StoredChat&TestCategory!=Images&TestCategory!=Uploads&TestCategory!=Moderations&TestCategory!=FineTuning&TestCategory!=Conversation&TestCategory!=Manual"
5959
--logger "trx;LogFilePrefix=live"
6060
--results-directory ${{ github.workspace }}/artifacts/test-results
6161
${{ env.version_suffix_args }}
@@ -69,16 +69,67 @@ jobs:
6969
name: build-artifacts
7070
path: ${{ github.workspace }}/artifacts
7171

72+
sign:
73+
needs: build
74+
runs-on: windows-latest # Code signing must run on a Windows agent for Authenticode signing (dll/exe)
75+
environment: release # Needed for OIDC subject for releases triggered on release being created.
76+
permissions:
77+
id-token: write # Required for requesting the JWT
78+
79+
steps:
80+
- name: Download build artifacts
81+
uses: actions/download-artifact@v4
82+
with:
83+
name: build-artifacts
84+
path: ${{ github.workspace }}/build-artifacts
85+
86+
- name: Setup .NET
87+
uses: actions/setup-dotnet@v3
88+
with:
89+
dotnet-version: '9.x'
90+
91+
- name: Install Sign CLI tool
92+
run: dotnet tool install --tool-path . --prerelease sign
93+
94+
- name: 'Az CLI login'
95+
uses: azure/login@v2
96+
with:
97+
client-id: 80125de0-6f58-4f16-bd05-b2fa621d36a5
98+
tenant-id: 16076fdc-fcc1-4a15-b1ca-32c9a255900e
99+
allow-no-subscriptions: true
100+
101+
- name: Sign artifacts
102+
shell: pwsh
103+
run: >
104+
./sign code azure-key-vault
105+
**/*.nupkg
106+
--base-directory "${{ github.workspace }}/build-artifacts/packages"
107+
--publisher-name "OpenAI"
108+
--description "OpenAI library for .NET"
109+
--description-url "https://github.com/openai/openai-dotnet"
110+
--azure-credential-type "azure-cli"
111+
--azure-key-vault-url "https://sc-openaisdk.vault.azure.net/"
112+
--azure-key-vault-certificate "OpenAISDKSCCert"
113+
114+
- name: Upload signed artifact
115+
uses: actions/upload-artifact@v4
116+
with:
117+
name: build-artifacts-signed
118+
path: ${{ github.workspace }}/build-artifacts
119+
72120
deploy:
73121
name: Publish Package
74-
needs: build
122+
needs: sign
75123
runs-on: ubuntu-latest
76124
steps:
77125
- name: Checkout code
78126
uses: actions/checkout@v2
79127

80128
- name: Download build artifacts
81129
uses: actions/download-artifact@v4
130+
with:
131+
name: build-artifacts-signed
132+
path: ${{ github.workspace }}/build-artifacts
82133

83134
- name: Upload release asset
84135
if: github.event_name == 'release'
@@ -92,6 +143,13 @@ jobs:
92143
run: |
93144
gh release edit "${{ github.event.release.tag_name }}" \
94145
--notes "See full changelog: ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.event.release.tag_name }}/CHANGELOG.md"
146+
env:
147+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
148+
149+
- name: Setup .NET
150+
uses: actions/setup-dotnet@v3
151+
with:
152+
dotnet-version: '9.x'
95153

96154
- name: NuGet authenticate
97155
run: dotnet nuget add source
@@ -114,4 +172,4 @@ jobs:
114172
${{ github.workspace }}/build-artifacts/packages/*.nupkg
115173
--source https://api.nuget.org/v3/index.json
116174
--api-key ${{ secrets.NUGET_API_KEY }}
117-
--skip-duplicate
175+
--skip-duplicate
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Update TypeSpec Generator Version
2+
3+
on:
4+
schedule:
5+
# Run weekly on Mondays at 9 AM UTC
6+
- cron: '0 9 * * 1'
7+
workflow_dispatch:
8+
# Allow manual triggering
9+
repository_dispatch:
10+
# Allow triggering from TypeSpec repository on new releases
11+
types: [typespec-release]
12+
13+
jobs:
14+
update-generator:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: write
18+
pull-requests: write
19+
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v4
23+
with:
24+
token: ${{ secrets.GITHUB_TOKEN }}
25+
26+
- name: Setup Node.js
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: '22.x'
30+
31+
- name: Setup .NET
32+
uses: actions/setup-dotnet@v4
33+
with:
34+
dotnet-version: 8.x
35+
36+
- name: Check for generator updates
37+
id: check-updates
38+
run: |
39+
# Get current version from the OpenAI package.json file
40+
CURRENT_VERSION=$(node -p "require('./codegen/package.json').dependencies['@typespec/http-client-csharp']" 2>/dev/null || echo "unknown")
41+
42+
echo "Current OpenAI version: $CURRENT_VERSION"
43+
44+
# Get latest version from npm registry
45+
LATEST_VERSION=$(npm view @typespec/http-client-csharp version 2>/dev/null || echo "unknown")
46+
echo "Latest version from npm: $LATEST_VERSION"
47+
48+
# Validate we got valid versions
49+
if [ "$CURRENT_VERSION" = "unknown" ] || [ "$LATEST_VERSION" = "unknown" ]; then
50+
echo "Error: Failed to get version information"
51+
echo "Current: $CURRENT_VERSION, Latest: $LATEST_VERSION"
52+
exit 1
53+
fi
54+
55+
# Compare versions (simple string comparison for alpha versions)
56+
if [ "$CURRENT_VERSION" != "$LATEST_VERSION" ]; then
57+
echo "Update needed: $CURRENT_VERSION -> $LATEST_VERSION"
58+
echo "needs-update=true" >> $GITHUB_OUTPUT
59+
echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
60+
echo "latest-version=$LATEST_VERSION" >> $GITHUB_OUTPUT
61+
else
62+
echo "No update needed - already at latest version: $CURRENT_VERSION"
63+
echo "needs-update=false" >> $GITHUB_OUTPUT
64+
fi
65+
66+
- name: Update generator version and create PR
67+
if: steps.check-updates.outputs.needs-update == 'true'
68+
run: |
69+
LATEST_VERSION="${{ steps.check-updates.outputs.latest-version }}"
70+
71+
# Use the PowerShell script to handle the entire update process (following TypeSpec pattern)
72+
pwsh ./scripts/Submit-GeneratorUpdatePr.ps1 \
73+
-PackageVersion "$LATEST_VERSION" \
74+
-AuthToken "${{ secrets.GITHUB_TOKEN }}" \
75+
-RepoPath "."

.gitignore

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,11 @@ artifacts
178178
# Temporary typespec folders for typespec generation
179179
TempTypeSpecFiles/
180180

181-
# Artifacts from the generator
182-
tspCodeModel.json
183-
Configuration.json
184-
185-
# Base specification files
186-
specification/base/
181+
# Azure specification files
182+
specification/base/entrypoints/azure.v1
183+
specification/base/entrypoints/sdk.dotnet.azure
184+
specification/base/typespec.azure
185+
specification/base/typespec.azure.v1
187186

188187
# Generator default TypeSpec output
189188
codegen/tsp-output/

CHANGELOG.md

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,80 @@
11
# Release History
22

3-
## 2.3.0-beta.1 (Unreleased)
3+
## 2.3.0 (2025-08-01)
44

5-
### Other changes
5+
### Features Added
66

7-
- Updated to `System.ClientModel` 1.5.1, which contains a fix for a concurrency bug which could cause some applications running on the legacy .NET Framework to experience an infinite loop while deserializing service responses.
7+
- OpenAI.Audio:
8+
- Added the `Model` property to `AudioClient`.
9+
- Added constructors that can take a custom `AuthenticationPolicy` to `AudioClient`.
10+
- OpenAI.Batch:
11+
- Added new methods to `BatchClient`:
12+
- `GetBatch` and `GetBatchAsync`
13+
- Added constructors that can take a custom `AuthenticationPolicy` to `BatchClient`.
14+
- OpenAI.Chat:
15+
- Added new methods to `ChatClient`:
16+
- `UpdateChatCompletion` and `UpdateChatCompletionAsync`
17+
- `GetChatCompletions` and `GetChatCompletionsAsync`
18+
- `GetChatCompletionMessages` and `GetChatCompletionMessagesAsync`
19+
- Added the `Model` property to `ChatClient`.
20+
- Added constructors that can take a custom `AuthenticationPolicy` to `ChatClient`.
21+
- OpenAI.Containers:
22+
- Introduced the new `ContainersClient` to support the Containers API with protocol methods for the following operations:
23+
- `CreateContainer` and `CreateContainerAsync`
24+
- `GetContainers` and `GetContainersAsync`
25+
- `GetContainer` and `GetContainerAsync`
26+
- `DeleteContainer` and `DeleteContainerAsync`
27+
- `CreateContainerFile` and `CreateContainerFileAsync`
28+
- `GetContainerFiles` and `GetContainerFilesAsync`
29+
- `GetContainerFile` and `GetContainerFileAsync`
30+
- `GetContainerFileContent` and `GetContainerFileContentAsync`
31+
- `DeleteContainerFile` and `DeleteContainerFileAsync`
32+
- OpenAI.Embeddings:
33+
- Added the `Model` property to `EmbeddingClient`.
34+
- Added constructors that can take a custom `AuthenticationPolicy` to `EmbeddingClient`.
35+
- OpenAI.Evals:
36+
- Added constructors that can take a custom `AuthenticationPolicy` to `EvaluationClient`.
37+
- OpenAI.Files:
38+
- Added constructors that can take a custom `AuthenticationPolicy` to `OpenAIFileClient`.
39+
- OpenAI.FineTuning:
40+
- Added constructors that can take a custom `AuthenticationPolicy` to `FineTuningClient`.
41+
- OpenAI.Graders:
42+
- Introduced the new `GraderClient` to support the Graders API with protocol methods for the following operations:
43+
- `RunGrader` and `RunGraderAsync`
44+
- `ValidateGrader` and `ValidateGraderAsync`
45+
- OpenAI.Images:
46+
- Added the `Model` property to `ImageClient`.
47+
- Added constructors that can take a custom `AuthenticationPolicy` to `ImageClient`.
48+
- OpenAI.Models:
49+
- Added constructors that can take a custom `AuthenticationPolicy` to `OpenAIModelClient`.
50+
- OpenAI.Moderations:
51+
- Added the `Model` property to `ModerationClient`.
52+
- Added constructors that can take a custom `AuthenticationPolicy` to `ModerationClient`.
53+
- OpenAI.Realtime:
54+
- Enabled support for semantic voice activity detection (VAD) via the new `CreateSemanticVoiceActivityTurnDetectionOptions` method of `TurnDetectionOptions`.
55+
- OpenAI.Responses:
56+
- Added a model factory.
57+
- Added constructors that can take a custom `AuthenticationPolicy` to `OpenAIResponseClient`.
58+
- OpenAI.VectorStores:
59+
- Added constructors that can take a custom `AuthenticationPolicy` to `VectorStoreClient`.
60+
61+
### Bug Fixed
62+
63+
- OpenAI.Assistants:
64+
- Fixed an issue causing the `ImageDetail` property of `MessageContent` to not be serialized correctly.
65+
- OpenAI.Audio:
66+
- Added a check to all overloads of `TranscribeAudioStreaming` and `TranscribeAudioStreamingAsync` in the `AudioClient` to prevent using the `whisper-1` model, which does not support streaming and simply ignores the `stream` parameter.
67+
- OpenAI.Realtime:
68+
- Improved the disposal logic in `AsyncWebsocketMessageResultEnumerator` to prevent multiple disposals.
69+
- OpenAI.Responses:
70+
- Fixed an issue in code generation that caused the `StreamingResponseTextAnnotationAddedUpdate` class to not be generated correctly as part of the set of possible handles when streaming.
71+
- Fixed an issue in code generation that caused the `Status` property of `ReasoningResponseItem` and the `ReasoningStatus` enum to not be generated correctly and lead to incorrect behavior.
72+
73+
### Other Changes
874

9-
- Removed explicit `net6.0` target framework, as this version reached end-of-life in November, 2024 and is no longer maintained nor supported by Microsoft. This does not prevent using the OpenAI library on .NET 6, as the runtime will fallback to the `netstandard2.0` target.
75+
- The `OpenAI` NuGet package now contains signed binaries.
76+
- Updated the `System.ClientModel` dependency to version 1.5.1, which contains a fix for a concurrency bug which could cause some applications running on the legacy .NET Framework to experience an infinite loop while deserializing service responses.
77+
- Removed the explicit `net6.0` target framework, as this version reached end-of-life in November 2024 and is no longer maintained nor supported by Microsoft. This does not prevent using the OpenAI library on .NET 6, as the runtime will fallback to the `netstandard2.0` target.
1078

1179
## 2.2.0 (2025-07-02)
1280

@@ -283,7 +351,7 @@
283351
### Features Added
284352

285353
- Added a new `RealtimeConversationClient` in a corresponding scenario namespace. ([ff75da4](https://github.com/openai/openai-dotnet/commit/ff75da4167bc83fa85eb69ac142cab88a963ed06))
286-
- This maps to the new `/realtime` beta endpoint and is thus marked with a new `[Experimental("OPENAI002")]` diagnostic tag.
354+
- This maps to the new `/realtime` beta endpoint and is thus marked with a new `[Experimental("OPENAI002")]` diagnostic tag.
287355
- This is a very early version of the convenience surface and thus subject to significant change
288356
- Documentation and samples will arrive soon; in the interim, see [the scenario test files](/tests/RealtimeConversation) for basic usage
289357
- You can also find an external sample employing this client, together with Azure OpenAI support, at https://github.com/Azure-Samples/aoai-realtime-audio-sdk/tree/main/dotnet/samples/console
@@ -441,7 +509,7 @@
441509
### Breaking Changes
442510

443511
- Renamed `AudioClient`'s `GenerateSpeechFromText` methods to simply `GenerateSpeech`. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7))
444-
- Changed the type of `OpenAIFileInfo`'s `SizeInBytes` property from `long?` to `int?`. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7))
512+
- Changed the type of `OpenAIFileInfo`'s `SizeInBytes` property from `long?` to `int?`. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7))
445513

446514
### Bugs Fixed
447515

Configuration.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"package-name": "OpenAI",
3+
"unreferenced-types-handling": "keepAll",
4+
"disable-xml-docs": true
5+
}

README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,9 @@ Register the `ChatClient` as a singleton in your `Program.cs`:
151151
builder.Services.AddSingleton<ChatClient>(serviceProvider =>
152152
{
153153
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
154+
var model = "gpt-4o";
154155

155-
return new ChatClient(apiKey);
156+
return new ChatClient(model, apiKey);
156157
});
157158
```
158159

@@ -518,14 +519,19 @@ await foreach (StreamingResponseUpdate update
518519
},
519520
}))
520521
{
521-
if (update is StreamingResponseItemUpdate itemUpdate
522+
if (update is StreamingResponseOutputItemAddedUpdate itemUpdate
522523
&& itemUpdate.Item is ReasoningResponseItem reasoningItem)
523524
{
524525
Console.WriteLine($"[Reasoning] ({reasoningItem.Status})");
525526
}
526-
else if (update is StreamingResponseContentPartDeltaUpdate deltaUpdate)
527+
else if (update is StreamingResponseOutputItemAddedUpdate itemDone
528+
&& itemDone.Item is ReasoningResponseItem reasoningDone)
527529
{
528-
Console.Write(deltaUpdate.Text);
530+
Console.WriteLine($"[Reasoning DONE] ({reasoningDone.Status})");
531+
}
532+
else if (update is StreamingResponseOutputTextDeltaUpdate delta)
533+
{
534+
Console.Write(delta.Delta);
529535
}
530536
}
531537
```
@@ -1095,4 +1101,4 @@ By default, the client classes will automatically retry the following errors up
10951101

10961102
### Observability
10971103

1098-
OpenAI .NET library supports experimental distributed tracing and metrics with OpenTelemetry. Check out [Observability with OpenTelemetry](./docs/observability.md) for more details.
1104+
OpenAI .NET library supports experimental distributed tracing and metrics with OpenTelemetry. Check out [Observability with OpenTelemetry](./docs/observability.md) for more details.

0 commit comments

Comments
 (0)