Skip to content

Comments

Add IHostedFileClient and friends#7269

Open
stephentoub wants to merge 3 commits intodotnet:mainfrom
stephentoub:fileclient
Open

Add IHostedFileClient and friends#7269
stephentoub wants to merge 3 commits intodotnet:mainfrom
stephentoub:fileclient

Conversation

@stephentoub
Copy link
Member

@stephentoub stephentoub commented Feb 6, 2026

Adds an abstraction for interacting with files AI services host, for things like input and output of code interpreter.

Microsoft Reviewers: Open in CodeFlow

@stephentoub stephentoub requested review from a team as code owners February 6, 2026 05:00
Copilot AI review requested due to automatic review settings February 6, 2026 05:00
@github-actions github-actions bot added the area-ai Microsoft.Extensions.AI libraries label Feb 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive support for interacting with AI service-hosted files through a new IHostedFileClient interface and related abstractions. The feature enables uploading, downloading, and managing files used by AI services, particularly for code interpreter operations.

Changes:

  • Introduces IHostedFileClient interface with upload, download, get, list, and delete operations
  • Adds supporting types: HostedFile, HostedFileDownloadStream, and various options classes
  • Implements OpenAI provider integration with support for both standard Files API and container-scoped files
  • Includes DelegatingHostedFileClient base class for middleware patterns
  • Adds HostedFileClientBuilder for creating file client pipelines
  • Implements logging and OpenTelemetry middleware for observability
  • Provides comprehensive extension methods for common operations

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Shared/DiagnosticIds/DiagnosticIds.cs Adds AIFiles experimental diagnostic ID
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/IHostedFileClient.cs Core interface defining file operations
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFile.cs Metadata model for hosted files
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFileDownloadStream.cs Abstract stream base for file downloads
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFileClientOptions.cs Base options class with Scope and AdditionalProperties
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFile*Options.cs Specific option classes for each operation
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFileClientMetadata.cs Provider metadata model
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/DelegatingHostedFileClient.cs Base class for middleware implementations
src/Libraries/Microsoft.Extensions.AI.Abstractions/Files/HostedFileClientExtensions.cs Extension methods for common file operations
src/Libraries/Microsoft.Extensions.AI/Files/HostedFileClientBuilder.cs Builder for creating file client pipelines
src/Libraries/Microsoft.Extensions.AI/Files/HostedFileClientBuilderHostedFileClientExtensions.cs AsBuilder extension method
src/Libraries/Microsoft.Extensions.AI/Files/LoggingHostedFileClient.cs Logging middleware implementation
src/Libraries/Microsoft.Extensions.AI/Files/LoggingHostedFileClientBuilderExtensions.cs UseLogging extension
src/Libraries/Microsoft.Extensions.AI/Files/OpenTelemetryHostedFileClient.cs OpenTelemetry tracing/metrics middleware
src/Libraries/Microsoft.Extensions.AI/Files/OpenTelemetryHostedFileClientBuilderExtensions.cs UseOpenTelemetry extension
src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs Adds File.Name and File.Size constants
src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIHostedFileClient.cs OpenAI implementation with Files and Container API support
src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIFileDownloadStream.cs Download stream wrapper for OpenAI responses
src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIClientExtensions.cs AsIHostedFileClient extension methods
src/Libraries/Microsoft.Extensions.AI/Microsoft.Extensions.AI.csproj Enables MediaTypeMap injection
src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Defaults.cs Adds JSON serialization support
test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/TestHostedFileClient.cs Test helper implementation
test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Files/*.cs Unit tests for abstractions
test/Libraries/Microsoft.Extensions.AI.Tests/Files/*.cs Unit tests for middleware
test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/*.cs Unit and integration tests for OpenAI implementation
test/Libraries/Microsoft.Extensions.AI.Tests/Microsoft.Extensions.AI.Tests.csproj Links TestHostedFileClient

Adds an abstraction for interacting with files AI services host, for things like input and output of code interpreter.
- Missing GetRequiredService methods
- Disposing of caller's Stream in OpenAI upload
Copy link
Member

@ericstj ericstj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed abstractions

/// <summary>Gets the unique identifier of the file.</summary>
public string Id { get; }

/// <summary>Gets or sets the name of the file.</summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this contain path information? If so, what rules are applied to those paths -- presumably they need to be platform agnostic. It may be important for folks wanting to save/upload using platform-specific assumptions.

Id = Throw.IfNullOrWhitespace(id);
}

/// <summary>Gets the unique identifier of the file.</summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we call out the scope of uniqueness so that providers implement correctly?

string fileId,
HostedFileDeleteOptions? options = null,
CancellationToken cancellationToken = default);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do any providers expose the concept of "modify" for renaming or changing properties? What about patching a file with content?

/// <param name="fileName">The file name.</param>
public OpenAIFileDownloadStream(BinaryData data, string? mediaType, string? fileName)
{
_innerStream = data.ToStream();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this wraps a BinaryData it should override ToDataContentAsync and implement over the BinaryData similar to

contents.Add(new DataContent(image.ImageBytes.ToMemory(), contentType));


// Determine the final path
string finalPath = destinationPath;
if (Directory.Exists(destinationPath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// <summary>
/// Initializes a new instance of the <see cref="HostedFileClientOptions"/> class.
/// </summary>
private protected HostedFileClientOptions()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - so rather than share a single options that's a super set we have options that are "best" for each operation and put anything shared between all in the base. I suppose that's OK, it optimizes for all-shared and op-specific.

public string? Scope { get; set; }

/// <summary>Gets or sets additional properties for the request.</summary>
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need some raw representation (RawRepresentationFactory) for break glass? I can imagine some providers having advanced options.

[Experimental(DiagnosticIds.Experiments.AIFiles, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class HostedFileListOptions : HostedFileClientOptions
{
/// <summary>Gets or sets a purpose filter.</summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any other filter options supported by providers? Like a path filter or some-such?

/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[Experimental(DiagnosticIds.Experiments.AIFiles, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class HostedFile
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't actually have the file content, consider a name like HostedFileInfo or consider API that lets folks get the content from the file, presumably such API would also require the file to maintain a reference to the client that it's associated with.

public sealed class HostedFile
{
/// <summary>
/// Initializes a new instance of the <see cref="HostedFile"/> class.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In it's current form it looks like we only ever expect providers to instantiate this. I wonder why this is different than HostedFileContent?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-ai Microsoft.Extensions.AI libraries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants