Skip to content

Commit d30163b

Browse files
authored
Add ContainerFileCitationMessageAnnotation (#792)
* Added `ContainerFileCitationMessageAnnotation` as a class derived from `ResponseMessageAnnotation` * Renamed the following methods in the `ContainerClient`: * `GetContainerFileContent` --> `DownloadContainerFile` * `GetContainerFileContentAsync` --> `DownloadContainerFileAsync`
1 parent d4ba95c commit d30163b

20 files changed

+7317
-6741
lines changed

api/OpenAI.net8.0.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,10 @@ public class ContainerClient {
24492449
public virtual ClientResult<DeleteContainerFileResponse> DeleteContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
24502450
public virtual Task<ClientResult> DeleteContainerFileAsync(string containerId, string fileId, RequestOptions options);
24512451
public virtual Task<ClientResult<DeleteContainerFileResponse>> DeleteContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
2452+
public virtual ClientResult DownloadContainerFile(string containerId, string fileId, RequestOptions options);
2453+
public virtual ClientResult<BinaryData> DownloadContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
2454+
public virtual Task<ClientResult> DownloadContainerFileAsync(string containerId, string fileId, RequestOptions options);
2455+
public virtual Task<ClientResult<BinaryData>> DownloadContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
24522456
public virtual ClientResult GetContainer(string containerId, RequestOptions options);
24532457
public virtual ClientResult<ContainerResource> GetContainer(string containerId, CancellationToken cancellationToken = default);
24542458
public virtual Task<ClientResult> GetContainerAsync(string containerId, RequestOptions options);
@@ -2457,10 +2461,6 @@ public class ContainerClient {
24572461
public virtual ClientResult<ContainerFileResource> GetContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
24582462
public virtual Task<ClientResult> GetContainerFileAsync(string containerId, string fileId, RequestOptions options);
24592463
public virtual Task<ClientResult<ContainerFileResource>> GetContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
2460-
public virtual ClientResult GetContainerFileContent(string containerId, string fileId, RequestOptions options);
2461-
public virtual ClientResult<BinaryData> GetContainerFileContent(string containerId, string fileId, CancellationToken cancellationToken = default);
2462-
public virtual Task<ClientResult> GetContainerFileContentAsync(string containerId, string fileId, RequestOptions options);
2463-
public virtual Task<ClientResult<BinaryData>> GetContainerFileContentAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
24642464
public virtual CollectionResult<ContainerFileResource> GetContainerFiles(string containerId, ContainerFileCollectionOptions options = null, CancellationToken cancellationToken = default);
24652465
public virtual CollectionResult GetContainerFiles(string containerId, int? limit, string order, string after, RequestOptions options);
24662466
public virtual AsyncCollectionResult<ContainerFileResource> GetContainerFilesAsync(string containerId, ContainerFileCollectionOptions options = null, CancellationToken cancellationToken = default);
@@ -5040,6 +5040,19 @@ public class ComputerTool : ResponseTool, IJsonModel<ComputerTool>, IPersistable
50405040
public override readonly string ToString();
50415041
}
50425042
[Experimental("OPENAI001")]
5043+
public class ContainerFileCitationMessageAnnotation : ResponseMessageAnnotation, IJsonModel<ContainerFileCitationMessageAnnotation>, IPersistableModel<ContainerFileCitationMessageAnnotation> {
5044+
public ContainerFileCitationMessageAnnotation(string containerId, string fileId, int startIndex, int endIndex, string filename);
5045+
public string ContainerId { get; set; }
5046+
public int EndIndex { get; set; }
5047+
public string FileId { get; set; }
5048+
public string Filename { get; set; }
5049+
public int StartIndex { get; set; }
5050+
protected override ResponseMessageAnnotation JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
5051+
protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
5052+
protected override ResponseMessageAnnotation PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
5053+
protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
5054+
}
5055+
[Experimental("OPENAI001")]
50435056
public class CustomMcpToolCallApprovalPolicy : IJsonModel<CustomMcpToolCallApprovalPolicy>, IPersistableModel<CustomMcpToolCallApprovalPolicy> {
50445057
[EditorBrowsable(EditorBrowsableState.Never)]
50455058
[Experimental("SCME0001")]

api/OpenAI.netstandard2.0.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,10 @@ public class ContainerClient {
20962096
public virtual ClientResult<DeleteContainerFileResponse> DeleteContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
20972097
public virtual Task<ClientResult> DeleteContainerFileAsync(string containerId, string fileId, RequestOptions options);
20982098
public virtual Task<ClientResult<DeleteContainerFileResponse>> DeleteContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
2099+
public virtual ClientResult DownloadContainerFile(string containerId, string fileId, RequestOptions options);
2100+
public virtual ClientResult<BinaryData> DownloadContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
2101+
public virtual Task<ClientResult> DownloadContainerFileAsync(string containerId, string fileId, RequestOptions options);
2102+
public virtual Task<ClientResult<BinaryData>> DownloadContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
20992103
public virtual ClientResult GetContainer(string containerId, RequestOptions options);
21002104
public virtual ClientResult<ContainerResource> GetContainer(string containerId, CancellationToken cancellationToken = default);
21012105
public virtual Task<ClientResult> GetContainerAsync(string containerId, RequestOptions options);
@@ -2104,10 +2108,6 @@ public class ContainerClient {
21042108
public virtual ClientResult<ContainerFileResource> GetContainerFile(string containerId, string fileId, CancellationToken cancellationToken = default);
21052109
public virtual Task<ClientResult> GetContainerFileAsync(string containerId, string fileId, RequestOptions options);
21062110
public virtual Task<ClientResult<ContainerFileResource>> GetContainerFileAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
2107-
public virtual ClientResult GetContainerFileContent(string containerId, string fileId, RequestOptions options);
2108-
public virtual ClientResult<BinaryData> GetContainerFileContent(string containerId, string fileId, CancellationToken cancellationToken = default);
2109-
public virtual Task<ClientResult> GetContainerFileContentAsync(string containerId, string fileId, RequestOptions options);
2110-
public virtual Task<ClientResult<BinaryData>> GetContainerFileContentAsync(string containerId, string fileId, CancellationToken cancellationToken = default);
21112111
public virtual CollectionResult<ContainerFileResource> GetContainerFiles(string containerId, ContainerFileCollectionOptions options = null, CancellationToken cancellationToken = default);
21122112
public virtual CollectionResult GetContainerFiles(string containerId, int? limit, string order, string after, RequestOptions options);
21132113
public virtual AsyncCollectionResult<ContainerFileResource> GetContainerFilesAsync(string containerId, ContainerFileCollectionOptions options = null, CancellationToken cancellationToken = default);
@@ -4403,6 +4403,18 @@ public class ComputerTool : ResponseTool, IJsonModel<ComputerTool>, IPersistable
44034403
public static bool operator !=(ComputerToolEnvironment left, ComputerToolEnvironment right);
44044404
public override readonly string ToString();
44054405
}
4406+
public class ContainerFileCitationMessageAnnotation : ResponseMessageAnnotation, IJsonModel<ContainerFileCitationMessageAnnotation>, IPersistableModel<ContainerFileCitationMessageAnnotation> {
4407+
public ContainerFileCitationMessageAnnotation(string containerId, string fileId, int startIndex, int endIndex, string filename);
4408+
public string ContainerId { get; set; }
4409+
public int EndIndex { get; set; }
4410+
public string FileId { get; set; }
4411+
public string Filename { get; set; }
4412+
public int StartIndex { get; set; }
4413+
protected override ResponseMessageAnnotation JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
4414+
protected override void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options);
4415+
protected override ResponseMessageAnnotation PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options);
4416+
protected override BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options);
4417+
}
44064418
public class CustomMcpToolCallApprovalPolicy : IJsonModel<CustomMcpToolCallApprovalPolicy>, IPersistableModel<CustomMcpToolCallApprovalPolicy> {
44074419
[EditorBrowsable(EditorBrowsableState.Never)]
44084420
public ref JsonPatch Patch { get; }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using NUnit.Framework;
2+
using OpenAI.Containers;
3+
using OpenAI.Responses;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
9+
namespace OpenAI.Examples;
10+
11+
// This example uses experimental APIs which are subject to change. To use experimental APIs,
12+
// please acknowledge their experimental status by suppressing the corresponding warning.
13+
#pragma warning disable OPENAI001
14+
15+
public partial class ResponseExamples
16+
{
17+
[Test]
18+
public void Example10_CodeInterpreter()
19+
{
20+
OpenAIResponseClient client = new(model: "gpt-5", apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
21+
22+
CodeInterpreterToolContainer container = new(CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration());
23+
CodeInterpreterTool codeInterpreterTool = new(container);
24+
ResponseCreationOptions options = new()
25+
{
26+
Tools = { codeInterpreterTool }
27+
};
28+
29+
List<ResponseItem> inputItems =
30+
[
31+
ResponseItem.CreateUserMessageItem("Create an Excel spreadsheet that contains the mathematical times tables from 1-12 and make it available for download."),
32+
];
33+
34+
OpenAIResponse response = client.CreateResponse(inputItems, options);
35+
36+
MessageResponseItem message = response.OutputItems
37+
.OfType<MessageResponseItem>()
38+
.FirstOrDefault();
39+
40+
ResponseContentPart contentPart = message.Content
41+
.Where(part => part.Kind == ResponseContentPartKind.OutputText)
42+
.FirstOrDefault();
43+
44+
ContainerFileCitationMessageAnnotation containerFileCitation = contentPart.OutputTextAnnotations
45+
.OfType<ContainerFileCitationMessageAnnotation>()
46+
.FirstOrDefault();
47+
48+
// Download the file from the container and save it.
49+
ContainerClient containerClient = new(apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
50+
BinaryData fileBytes = containerClient.DownloadContainerFile(containerFileCitation.ContainerId, containerFileCitation.FileId);
51+
using FileStream stream = File.OpenWrite(containerFileCitation.Filename);
52+
fileBytes.ToStream().CopyTo(stream);
53+
}
54+
}
55+
56+
#pragma warning restore OPENAI001
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using NUnit.Framework;
2+
using OpenAI.Containers;
3+
using OpenAI.Responses;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Threading.Tasks;
9+
10+
namespace OpenAI.Examples;
11+
12+
// This example uses experimental APIs which are subject to change. To use experimental APIs,
13+
// please acknowledge their experimental status by suppressing the corresponding warning.
14+
#pragma warning disable OPENAI001
15+
16+
public partial class ResponseExamples
17+
{
18+
[Test]
19+
public async Task Example10_CodeInterpreterAsync()
20+
{
21+
OpenAIResponseClient client = new(model: "gpt-5", apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
22+
23+
CodeInterpreterToolContainer container = new(CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration());
24+
CodeInterpreterTool codeInterpreterTool = new(container);
25+
ResponseCreationOptions options = new()
26+
{
27+
Tools = { codeInterpreterTool }
28+
};
29+
30+
List<ResponseItem> inputItems =
31+
[
32+
ResponseItem.CreateUserMessageItem("Create an Excel spreadsheet that contains the mathematical times tables from 1-12 and make it available for download."),
33+
];
34+
35+
OpenAIResponse response = await client.CreateResponseAsync(inputItems, options);
36+
37+
MessageResponseItem message = response.OutputItems
38+
.OfType<MessageResponseItem>()
39+
.FirstOrDefault();
40+
41+
ResponseContentPart contentPart = message.Content
42+
.Where(part => part.Kind == ResponseContentPartKind.OutputText)
43+
.FirstOrDefault();
44+
45+
ContainerFileCitationMessageAnnotation containerFileCitation = contentPart.OutputTextAnnotations
46+
.OfType<ContainerFileCitationMessageAnnotation>()
47+
.FirstOrDefault();
48+
49+
// Download the file from the container and save it.
50+
ContainerClient containerClient = new(apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
51+
BinaryData fileBytes = await containerClient.DownloadContainerFileAsync(containerFileCitation.ContainerId, containerFileCitation.FileId);
52+
using FileStream stream = File.OpenWrite(containerFileCitation.Filename);
53+
fileBytes.ToStream().CopyTo(stream);
54+
}
55+
}
56+
57+
#pragma warning restore OPENAI001

specification/base/typespec/responses/models.tsp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,11 +1089,11 @@ model AnnotationUrlCitation extends Annotation {
10891089
}
10901090

10911091
/** A citation for a container file used to generate a model response. */
1092-
model ContainerFileCitationBody {
1092+
model ContainerFileCitationBody extends Annotation {
10931093
@doc("""
10941094
The type of the container file citation. Always `container_file_citation`.
10951095
""")
1096-
type: "container_file_citation" = "container_file_citation";
1096+
type: AnnotationType.container_file_citation;
10971097

10981098
/** The ID of the container file. */
10991099
container_id: string;
@@ -1106,6 +1106,9 @@ model ContainerFileCitationBody {
11061106

11071107
/** The index of the last character of the container file citation in the message. */
11081108
end_index: int32;
1109+
1110+
/** The filename of the container file cited. */
1111+
filename: string;
11091112
}
11101113

11111114
// Tool customization (apply_discriminator): Apply discriminated base type, rename for consistency and clarity

specification/client/containers.client.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ using Azure.ClientGenerator.Core;
66

77
@@clientName(Containers.retrieveContainer, "GetContainer");
88
@@clientName(Containers.retrieveContainerFile, "GetContainerFile");
9-
@@clientName(Containers.retrieveContainerFileContent, "GetContainerFileContent");
9+
@@clientName(Containers.retrieveContainerFileContent, "DownloadContainerFile");
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace OpenAI.Responses;
2+
3+
// CUSTOM: Renamed.
4+
[CodeGenType("ContainerFileCitationBody")]
5+
public partial class ContainerFileCitationMessageAnnotation
6+
{
7+
}

src/Custom/Responses/Annotations/FileCitationMessageAnnotation.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
namespace OpenAI.Responses;
22

3-
// CUSTOM:
4-
// - Renamed.
3+
// CUSTOM: Renamed.
54
[CodeGenType("AnnotationFileCitation")]
65
public partial class FileCitationMessageAnnotation
76
{

src/Custom/Responses/Annotations/FilePathMessageAnnotation.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
namespace OpenAI.Responses;
22

3-
// CUSTOM:
4-
// - Renamed.
3+
// CUSTOM: Renamed.
54
[CodeGenType("AnnotationFilePath")]
65
public partial class FilePathMessageAnnotation
76
{

src/Custom/Responses/Annotations/ResponseMessageAnnotationKind.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ namespace OpenAI.Responses;
99
[CodeGenType("AnnotationType")]
1010
public enum ResponseMessageAnnotationKind
1111
{
12+
[CodeGenMember("FileCitation")]
1213
FileCitation,
1314

1415
[CodeGenMember("UrlCitation")]
1516
UriCitation,
1617

18+
[CodeGenMember("FilePath")]
1719
FilePath,
1820

21+
[CodeGenMember("ContainerFileCitation")]
1922
ContainerFileCitation
2023
}

0 commit comments

Comments
 (0)