.NET: Add container file download extension for Code Interpreter cfile_ IDs#5014
.NET: Add container file download extension for Code Interpreter cfile_ IDs#5014chetantoshniwal wants to merge 2 commits intomicrosoft:mainfrom
Conversation
…microsoft#3081) Add OpenAIClientContainerFileExtensions with DownloadContainerFileAsync extension method on OpenAIClient. Files generated by Code Interpreter have cfile_ prefixed IDs and reside in containers, requiring the Containers API instead of the standard Files API. This extension provides a discoverable way to download these container-scoped files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
chetantoshniwal
left a comment
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 86%
✓ Correctness
The PR adds a thin extension method on OpenAIClient to download container files, plus comprehensive input-validation unit tests. The implementation is clean: argument guards use the shared Throw helper consistently, the CancellationToken is forwarded correctly, the namespace follows existing conventions (OpenAI extensions live in the OpenAI namespace), and the [Experimental] attribute matches other extension classes. The tests correctly expect ArgumentNullException for null inputs and ArgumentException for empty/whitespace, matching the Throw.IfNullOrWhitespace behavior. No correctness issues found.
✓ Security Reliability
This PR adds a clean extension method for downloading OpenAI container files, with proper input validation via the established Throw helpers, correct CancellationToken propagation, and ConfigureAwait(false) for library code. The method follows the same patterns used by other extension methods in the project (e.g., OpenAIResponseClientExtensions). Tests cover all guard-clause branches. No security or reliability concerns were identified — there are no injection risks, resource leaks, secrets, or unhandled failure modes.
✗ Test Coverage
The test file thoroughly covers all input-validation guard clauses (null, empty, and whitespace for both containerId and fileId, plus null client), which is good. However, there is no happy-path test verifying that when valid arguments are supplied, the method actually delegates to
client.GetContainerClient().DownloadContainerFileAsync(...)with the correct arguments and propagates the CancellationToken. The tests only exercise the threeThrow.*lines (lines 39-41 of the production code) and never reach the actual business logic on lines 43-44. This is a significant gap: without a happy-path test, a regression that breaks the delegation or drops the CancellationToken would go undetected.
✓ Design Approach
The extension follows the established pattern in this codebase (thin validated wrapper over an SDK method, placed in the SDK's namespace) and the implementation itself is sound. The only meaningful gap is the complete absence of a happy-path test: all seven tests exercise pre-condition validation that fires before the method reaches
GetContainerClient().DownloadContainerFileAsync(), so the actual delegation logic—the one line of real behaviour—is entirely untested. If the underlying SDK method is mockable or the OpenAIClient subclass approach already used in the test file can be extended to stub the container client, a success-case test should be added.
Flagged Issues
- No happy-path test: the core behavior of the method — obtaining a ContainerClient and calling DownloadContainerFileAsync with the correct containerId, fileId, and CancellationToken (lines 43-44) — is completely untested. All seven tests only cover argument-validation guard clauses.
Suggestions
- Add a happy-path test that extends the existing TestOpenAIClient stub (similar to the pattern in OpenAIAssistantClientExtensionsTests) to intercept GetContainerClient().DownloadContainerFileAsync, then verify that the extension correctly delegates with the expected containerId, fileId, and CancellationToken and returns the expected ClientResult.
- Consider adding a test that verifies CancellationToken propagation — e.g., passing a pre-cancelled token and asserting it is forwarded to the underlying SDK call.
Automated review by chetantoshniwal's agents
| public TestOpenAIClient() | ||
| { | ||
| } | ||
| } |
There was a problem hiding this comment.
The TestOpenAIClient stub is only sufficient for guard-clause tests. To test the actual delegation behavior (lines 43-44 of the production code), extend this type or add a separate test fixture that overides GetContainerClient() to capture and assert that the correct containerId, fileId, and CancellationToken are forwarded to DownloadContainerFileAsync.
There was a problem hiding this comment.
Pull request overview
Adds a .NET extension on OpenAIClient to download Code Interpreter container-scoped files (cfile_ within cntr_) via the Containers API, addressing the inability to download these files through the standard Files API.
Changes:
- Added
OpenAIClientContainerFileExtensions.DownloadContainerFileAsyncto route downloads throughGetContainerClient(). - Added unit tests covering null/empty/whitespace argument guards for
client,containerId, andfileId.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIClientContainerFileExtensions.cs | New OpenAIClient extension method to download container-scoped cfile_ outputs via Containers API. |
| dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIClientContainerFileExtensionsTests.cs | New unit tests validating argument guard behavior for the new extension method. |
dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIClientContainerFileExtensions.cs
Outdated
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIClientContainerFileExtensions.cs
Outdated
Show resolved
Hide resolved
| Throw.IfNull(client); | ||
| Throw.IfNullOrWhitespace(containerId); | ||
| Throw.IfNullOrWhitespace(fileId); | ||
|
|
||
| var containerClient = client.GetContainerClient(); | ||
| return await containerClient.DownloadContainerFileAsync(containerId, fileId, cancellationToken).ConfigureAwait(false); | ||
| } |
There was a problem hiding this comment.
Current tests only validate argument guards; there’s no coverage that a valid call actually routes through GetContainerClient().DownloadContainerFileAsync(...) (the core behavior this PR adds). Consider adding a positive-path test using a custom transport / pipeline to assert the request goes to the Containers API endpoint and succeeds (without requiring real network calls).
There was a problem hiding this comment.
@copilot apply changes based on this feedback
.../Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIClientContainerFileExtensionsTests.cs
Outdated
Show resolved
Hide resolved
.../Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIClientContainerFileExtensionsTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Motivation and Context
Azure OpenAI Responses API Code Interpreter generates files with
cfile_IDs that live inside containers (cntr_IDs). The standard Files API (GetOpenAIFileClient) cannot download these container-scoped files, leaving users unable to retrieve Code Interpreter output.Fixes #3081
Description
The root cause is that container files require the Containers API (
GetContainerClient) rather than the Files API. This change adds a newOpenAIClientContainerFileExtensionsclass with aDownloadContainerFileAsyncextension method onOpenAIClientthat routes downloads throughGetContainerClient().DownloadContainerFileAsync(containerId, fileId). Unit tests validate argument guard behavior for null, empty, and whitespace inputs on bothcontainerIdandfileIdparameters.Contribution Checklist