openai/openai-dotnet

Public

mirrored from https://github.com/openai/openai-dotnetAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.0.0-beta.7

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/Custom/Assistants/AssistantClient.cs

992lines · modecode

1using System;
2using System.ClientModel;
3using System.ClientModel.Primitives;
4using System.Collections.Generic;
5using System.Diagnostics.CodeAnalysis;
6using System.Linq;
7using System.Runtime.CompilerServices;
8using System.Threading;
9using System.Threading.Tasks;
10using static OpenAI.InternalListHelpers;
11
12namespace OpenAI.Assistants;
13
14/// <summary>
15/// The service client for OpenAI assistants.
16/// </summary>
17[Experimental("OPENAI001")]
18[CodeGenClient("Assistants")]
19[CodeGenSuppress("AssistantClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))]
20[CodeGenSuppress("CreateAssistantAsync", typeof(AssistantCreationOptions))]
21[CodeGenSuppress("CreateAssistant", typeof(AssistantCreationOptions))]
22[CodeGenSuppress("DeleteAssistantAsync", typeof(string))]
23[CodeGenSuppress("DeleteAssistant", typeof(string))]
24[CodeGenSuppress("GetAssistantsAsync", typeof(int?), typeof(ListOrder?), typeof(string), typeof(string))]
25[CodeGenSuppress("GetAssistants", typeof(int?), typeof(ListOrder?), typeof(string), typeof(string))]
26public partial class AssistantClient
27{
28 private readonly InternalAssistantMessageClient _messageSubClient;
29 private readonly InternalAssistantRunClient _runSubClient;
30 private readonly InternalAssistantThreadClient _threadSubClient;
31
32 /// <summary>
33 /// Initializes a new instance of <see cref="AssistantClient"/> that will use an API key when authenticating.
34 /// </summary>
35 /// <param name="credential"> The API key used to authenticate with the service endpoint. </param>
36 /// <param name="options"> Additional options to customize the client. </param>
37 /// <exception cref="ArgumentNullException"> The provided <paramref name="credential"/> was null. </exception>
38 public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options = default)
39 : this(
40 OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options),
41 OpenAIClient.GetEndpoint(options),
42 options)
43 { }
44
45 /// <summary>
46 /// Initializes a new instance of <see cref="AssistantClient"/> that will use an API key from the OPENAI_API_KEY
47 /// environment variable when authenticating.
48 /// </summary>
49 /// <remarks>
50 /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like
51 /// <see cref="AssistantClient(ApiKeyCredential,OpenAIClientOptions)"/>.
52 /// </remarks>
53 /// <param name="options"> Additional options to customize the client. </param>
54 /// <exception cref="InvalidOperationException"> The OPENAI_API_KEY environment variable was not found. </exception>
55 public AssistantClient(OpenAIClientOptions options = default)
56 : this(
57 OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options),
58 OpenAIClient.GetEndpoint(options),
59 options)
60 { }
61
62 /// <summary> Initializes a new instance of <see cref="AssistantClient"/>. </summary>
63 /// <param name="pipeline"> The HTTP pipeline for sending and receiving REST requests and responses. </param>
64 /// <param name="endpoint"> OpenAI Endpoint. </param>
65 /// <param name="options"> Client-wide options to propagate settings from. </param>
66 protected internal AssistantClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options)
67 {
68 _pipeline = pipeline;
69 _endpoint = endpoint;
70 _messageSubClient = new(_pipeline, _endpoint, options);
71 _runSubClient = new(_pipeline, _endpoint, options);
72 _threadSubClient = new(_pipeline, _endpoint, options);
73 }
74
75 /// <summary> Creates a new assistant. </summary>
76 /// <param name="model"> The default model that the assistant should use. </param>
77 /// <param name="options"> The additional <see cref="AssistantCreationOptions"/> to use. </param>
78 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
79 /// <exception cref="ArgumentException"> <paramref name="model"/> is null or empty. </exception>
80 public virtual async Task<ClientResult<Assistant>> CreateAssistantAsync(string model, AssistantCreationOptions options = null, CancellationToken cancellationToken = default)
81 {
82 Argument.AssertNotNullOrEmpty(model, nameof(model));
83 options ??= new();
84 options.Model = model;
85
86 ClientResult protocolResult = await CreateAssistantAsync(options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
87 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
88 }
89
90 /// <summary> Creates a new assistant. </summary>
91 /// <param name="model"> The default model that the assistant should use. </param>
92 /// <param name="options"> The additional <see cref="AssistantCreationOptions"/> to use. </param>
93 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
94 /// <exception cref="ArgumentException"> <paramref name="model"/> is null or empty. </exception>
95 public virtual ClientResult<Assistant> CreateAssistant(string model, AssistantCreationOptions options = null, CancellationToken cancellationToken = default)
96 {
97 Argument.AssertNotNullOrEmpty(model, nameof(model));
98 options ??= new();
99 options.Model = model;
100
101 ClientResult protocolResult = CreateAssistant(options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
102 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
103 }
104
105 /// <summary>
106 /// Returns a collection of <see cref="Assistant"/> instances.
107 /// </summary>
108 /// <param name="resultOrder">
109 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
110 /// timestamp.
111 /// </param>
112 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
113 /// <returns> A collection of assistants that can be enumerated using <c>await foreach</c>. </returns>
114 public virtual AsyncPageableCollection<Assistant> GetAssistantsAsync(ListOrder? resultOrder = null, CancellationToken cancellationToken = default)
115 {
116 return CreateAsyncPageable<Assistant, InternalListAssistantsResponse>((continuationToken, pageSize)
117 => GetAssistantsAsync(pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
118 }
119
120 /// <summary>
121 /// Returns a collection of <see cref="Assistant"/> instances.
122 /// </summary>
123 /// <param name="resultOrder">
124 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
125 /// timestamp.
126 /// </param>
127 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
128 /// <returns> A collection of assistants that can be enumerated using <c>foreach</c>. </returns>
129 public virtual PageableCollection<Assistant> GetAssistants(ListOrder? resultOrder = null, CancellationToken cancellationToken = default)
130 {
131 return CreatePageable<Assistant, InternalListAssistantsResponse>((continuationToken, pageSize)
132 => GetAssistants(pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
133 }
134
135 /// <summary>
136 /// Deletes an existing <see cref="Assistant"/>.
137 /// </summary>
138 /// <param name="assistantId"> The ID of the assistant to delete. </param>
139 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
140 /// <returns> A value indicating whether the deletion was successful. </returns>
141 public virtual async Task<ClientResult<bool>> DeleteAssistantAsync(string assistantId, CancellationToken cancellationToken = default)
142 {
143 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
144
145 ClientResult protocolResult = await DeleteAssistantAsync(assistantId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
146 return CreateResultFromProtocol(protocolResult, response
147 => InternalDeleteAssistantResponse.FromResponse(response).Deleted);
148 }
149
150 /// <summary>
151 /// Deletes an existing <see cref="Assistant"/>.
152 /// </summary>
153 /// <param name="assistantId"> The ID of the assistant to delete. </param>
154 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
155 /// <returns> A value indicating whether the deletion was successful. </returns>
156 public virtual ClientResult<bool> DeleteAssistant(string assistantId, CancellationToken cancellationToken = default)
157 {
158 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
159
160 ClientResult protocolResult = DeleteAssistant(assistantId, cancellationToken.ToRequestOptions());
161 return CreateResultFromProtocol(protocolResult, response
162 => InternalDeleteAssistantResponse.FromResponse(response).Deleted);
163 }
164
165 /// <summary>
166 /// Creates a new <see cref="AssistantThread"/>.
167 /// </summary>
168 /// <param name="options"> Additional options to use when creating the thread. </param>
169 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
170 /// <returns> A new thread. </returns>
171 public virtual async Task<ClientResult<AssistantThread>> CreateThreadAsync(ThreadCreationOptions options = null, CancellationToken cancellationToken = default)
172 {
173 ClientResult protocolResult = await CreateThreadAsync(options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
174 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
175 }
176
177 /// <summary>
178 /// Creates a new <see cref="AssistantThread"/>.
179 /// </summary>
180 /// <param name="options"> Additional options to use when creating the thread. </param>
181 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
182 /// <returns> A new thread. </returns>
183 public virtual ClientResult<AssistantThread> CreateThread(ThreadCreationOptions options = null, CancellationToken cancellationToken = default)
184 {
185 ClientResult protocolResult = CreateThread(options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
186 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
187 }
188
189 /// <summary>
190 /// Gets an existing <see cref="AssistantThread"/>, retrieved via a known ID.
191 /// </summary>
192 /// <param name="threadId"> The ID of the thread to retrieve. </param>
193 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
194 /// <returns> The existing thread instance. </returns>
195 public virtual async Task<ClientResult<AssistantThread>> GetThreadAsync(string threadId, CancellationToken cancellationToken = default)
196 {
197 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
198
199 ClientResult protocolResult = await GetThreadAsync(threadId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
200 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
201 }
202
203 /// <summary>
204 /// Gets an existing <see cref="AssistantThread"/>, retrieved via a known ID.
205 /// </summary>
206 /// <param name="threadId"> The ID of the thread to retrieve. </param>
207 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
208 /// <returns> The existing thread instance. </returns>
209 public virtual ClientResult<AssistantThread> GetThread(string threadId, CancellationToken cancellationToken = default)
210 {
211 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
212
213 ClientResult protocolResult = GetThread(threadId, cancellationToken.ToRequestOptions());
214 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
215 }
216
217 /// <summary>
218 /// Modifies an existing <see cref="AssistantThread"/>.
219 /// </summary>
220 /// <param name="threadId"> The ID of the thread to modify. </param>
221 /// <param name="options"> The modifications to apply to the thread. </param>
222 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
223 /// <returns> The updated <see cref="AssistantThread"/> instance. </returns>
224 public virtual async Task<ClientResult<AssistantThread>> ModifyThreadAsync(string threadId, ThreadModificationOptions options, CancellationToken cancellationToken = default)
225 {
226 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
227 Argument.AssertNotNull(options, nameof(options));
228
229 ClientResult protocolResult = await ModifyThreadAsync(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
230 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
231 }
232
233 /// <summary>
234 /// Modifies an existing <see cref="AssistantThread"/>.
235 /// </summary>
236 /// <param name="threadId"> The ID of the thread to modify. </param>
237 /// <param name="options"> The modifications to apply to the thread. </param>
238 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
239 /// <returns> The updated <see cref="AssistantThread"/> instance. </returns>
240 public virtual ClientResult<AssistantThread> ModifyThread(string threadId, ThreadModificationOptions options, CancellationToken cancellationToken = default)
241 {
242 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
243 Argument.AssertNotNull(options, nameof(options));
244
245 ClientResult protocolResult = ModifyThread(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
246 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
247 }
248
249 /// <summary>
250 /// Deletes an existing <see cref="AssistantThread"/>.
251 /// </summary>
252 /// <param name="threadId"> The ID of the thread to delete. </param>
253 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
254 /// <returns> A value indicating whether the deletion was successful. </returns>
255 public virtual async Task<ClientResult<bool>> DeleteThreadAsync(string threadId, CancellationToken cancellationToken = default)
256 {
257 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
258
259 ClientResult protocolResult = await DeleteThreadAsync(threadId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
260 return CreateResultFromProtocol(protocolResult, response
261 => InternalDeleteThreadResponse.FromResponse(response).Deleted);
262 }
263
264 /// <summary>
265 /// Deletes an existing <see cref="AssistantThread"/>.
266 /// </summary>
267 /// <param name="threadId"> The ID of the thread to delete. </param>
268 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
269 /// <returns> A value indicating whether the deletion was successful. </returns>
270 public virtual ClientResult<bool> DeleteThread(string threadId, CancellationToken cancellationToken = default)
271 {
272 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
273
274 ClientResult protocolResult = DeleteThread(threadId, cancellationToken.ToRequestOptions());
275 return CreateResultFromProtocol(protocolResult, response
276 => InternalDeleteThreadResponse.FromResponse(response).Deleted);
277 }
278
279 /// <summary>
280 /// Creates a new <see cref="ThreadMessage"/> on an existing <see cref="AssistantThread"/>.
281 /// </summary>
282 /// <param name="threadId"> The ID of the thread to associate the new message with. </param>
283 /// <param name="role"> The role to associate with the new message. </param>
284 /// <param name="content"> The collection of <see cref="MessageContent"/> items for the message. </param>
285 /// <param name="options"> Additional options to apply to the new message. </param>
286 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
287 /// <returns> A new <see cref="ThreadMessage"/>. </returns>
288 public virtual async Task<ClientResult<ThreadMessage>> CreateMessageAsync(
289 string threadId,
290 MessageRole role,
291 IEnumerable<MessageContent> content,
292 MessageCreationOptions options = null,
293 CancellationToken cancellationToken = default)
294 {
295 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
296 options ??= new();
297 options.Role = role;
298 options.Content.Clear();
299 foreach (MessageContent contentItem in content)
300 {
301 options.Content.Add(contentItem);
302 }
303
304 ClientResult protocolResult = await CreateMessageAsync(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions())
305 .ConfigureAwait(false);
306 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
307 }
308
309 /// <summary>
310 /// Creates a new <see cref="ThreadMessage"/> on an existing <see cref="AssistantThread"/>.
311 /// </summary>
312 /// <param name="threadId"> The ID of the thread to associate the new message with. </param>
313 /// <param name="role"> The role to associate with the new message. </param>
314 /// <param name="content"> The collection of <see cref="MessageContent"/> items for the message. </param>
315 /// <param name="options"> Additional options to apply to the new message. </param>
316 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
317 /// <returns> A new <see cref="ThreadMessage"/>. </returns>
318 public virtual ClientResult<ThreadMessage> CreateMessage(
319 string threadId,
320 MessageRole role,
321 IEnumerable<MessageContent> content,
322 MessageCreationOptions options = null,
323 CancellationToken cancellationToken = default)
324 {
325 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
326 options ??= new();
327 options.Role = role;
328 options.Content.Clear();
329 foreach (MessageContent contentItem in content)
330 {
331 options.Content.Add(contentItem);
332 }
333
334 ClientResult protocolResult = CreateMessage(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
335 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
336 }
337
338 /// <summary>
339 /// Returns a collection of <see cref="ThreadMessage"/> instances from an existing <see cref="AssistantThread"/>.
340 /// </summary>
341 /// <param name="threadId"> The ID of the thread to list messages from. </param>
342 /// <param name="resultOrder">
343 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
344 /// timestamp.
345 /// </param>
346 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
347 /// <returns> A collection of messages that can be enumerated using <c>await foreach</c>. </returns>
348 public virtual AsyncPageableCollection<ThreadMessage> GetMessagesAsync(
349 string threadId,
350 ListOrder? resultOrder = null,
351 CancellationToken cancellationToken = default)
352 {
353 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
354
355 return CreateAsyncPageable<ThreadMessage, InternalListMessagesResponse>((continuationToken, pageSize)
356 => GetMessagesAsync(threadId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
357 }
358
359 /// <summary>
360 /// Returns a collection of <see cref="ThreadMessage"/> instances from an existing <see cref="AssistantThread"/>.
361 /// </summary>
362 /// <param name="threadId"> The ID of the thread to list messages from. </param>
363 /// <param name="resultOrder">
364 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
365 /// timestamp.
366 /// </param>
367 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
368 /// <returns> A collection of messages that can be enumerated using <c>foreach</c>. </returns>
369 public virtual PageableCollection<ThreadMessage> GetMessages(
370 string threadId,
371 ListOrder? resultOrder = null,
372 CancellationToken cancellationToken = default)
373 {
374 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
375
376 return CreatePageable<ThreadMessage, InternalListMessagesResponse>((continuationToken, pageSize)
377 => GetMessages(threadId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
378 }
379
380 /// <summary>
381 /// Gets an existing <see cref="ThreadMessage"/> from a known <see cref="AssistantThread"/>.
382 /// </summary>
383 /// <param name="threadId"> The ID of the thread to retrieve the message from. </param>
384 /// <param name="messageId"> The ID of the message to retrieve. </param>
385 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
386 /// <returns> The existing <see cref="ThreadMessage"/> instance. </returns>
387 public virtual async Task<ClientResult<ThreadMessage>> GetMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default)
388 {
389 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
390 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
391
392 ClientResult protocolResult = await GetMessageAsync(threadId, messageId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
393 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
394 }
395
396 /// <summary>
397 /// Gets an existing <see cref="ThreadMessage"/> from a known <see cref="AssistantThread"/>.
398 /// </summary>
399 /// <param name="threadId"> The ID of the thread to retrieve the message from. </param>
400 /// <param name="messageId"> The ID of the message to retrieve. </param>
401 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
402 /// <returns> The existing <see cref="ThreadMessage"/> instance. </returns>
403 public virtual ClientResult<ThreadMessage> GetMessage(string threadId, string messageId, CancellationToken cancellationToken = default)
404 {
405 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
406 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
407
408 ClientResult protocolResult = GetMessage(threadId, messageId, cancellationToken.ToRequestOptions());
409 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
410 }
411
412 /// <summary>
413 /// Modifies an existing <see cref="ThreadMessage"/>.
414 /// </summary>
415 /// <param name="threadId"> The ID of the thread associated with the message to modify. </param>
416 /// <param name="messageId"> The ID of the message to modify. </param>
417 /// <param name="options"> The changes to apply to the message. </param>
418 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
419 /// <returns> The updated <see cref="ThreadMessage"/>. </returns>
420 public virtual async Task<ClientResult<ThreadMessage>> ModifyMessageAsync(string threadId, string messageId, MessageModificationOptions options, CancellationToken cancellationToken = default)
421 {
422 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
423 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
424 Argument.AssertNotNull(options, nameof(options));
425
426 ClientResult protocolResult = await ModifyMessageAsync(threadId, messageId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions())
427 .ConfigureAwait(false);
428 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
429 }
430
431 /// <summary>
432 /// Modifies an existing <see cref="ThreadMessage"/>.
433 /// </summary>
434 /// <param name="threadId"> The ID of the thread associated with the message to modify. </param>
435 /// <param name="messageId"> The ID of the message to modify. </param>
436 /// <param name="options"> The changes to apply to the message. </param>
437 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
438 /// <returns> The updated <see cref="ThreadMessage"/>. </returns>
439 public virtual ClientResult<ThreadMessage> ModifyMessage(string threadId, string messageId, MessageModificationOptions options, CancellationToken cancellationToken = default)
440 {
441 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
442 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
443 Argument.AssertNotNull(options, nameof(options));
444
445 ClientResult protocolResult = ModifyMessage(threadId, messageId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
446 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
447 }
448
449 /// <summary>
450 /// Deletes an existing <see cref="ThreadMessage"/>.
451 /// </summary>
452 /// <param name="threadId"> The ID of the thread associated with the message. </param>
453 /// <param name="messageId"> The ID of the message. </param>
454 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
455 /// <returns> A value indicating whether the deletion was successful. </returns>
456 public virtual async Task<ClientResult<bool>> DeleteMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default)
457 {
458 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
459 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
460
461 ClientResult protocolResult = await DeleteMessageAsync(threadId, messageId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
462 return CreateResultFromProtocol(protocolResult, response =>
463 InternalDeleteMessageResponse.FromResponse(response).Deleted);
464 }
465
466 /// <summary>
467 /// Deletes an existing <see cref="ThreadMessage"/>.
468 /// </summary>
469 /// <param name="threadId"> The ID of the thread associated with the message. </param>
470 /// <param name="messageId"> The ID of the message. </param>
471 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
472 /// <returns> A value indicating whether the deletion was successful. </returns>
473 public virtual ClientResult<bool> DeleteMessage(string threadId, string messageId, CancellationToken cancellationToken = default)
474 {
475 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
476 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
477
478 ClientResult protocolResult = DeleteMessage(threadId, messageId, cancellationToken.ToRequestOptions());
479 return CreateResultFromProtocol(protocolResult, response =>
480 InternalDeleteMessageResponse.FromResponse(response).Deleted);
481 }
482
483 /// <summary>
484 /// Begins a new <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
485 /// <see cref="Assistant"/>.
486 /// </summary>
487 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
488 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
489 /// <param name="options"> Additional options for the run. </param>
490 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
491 /// <returns> A new <see cref="ThreadRun"/> instance. </returns>
492 public virtual async Task<ClientResult<ThreadRun>> CreateRunAsync(string threadId, string assistantId, RunCreationOptions options = null, CancellationToken cancellationToken = default)
493 {
494 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
495 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
496 options ??= new();
497 options.AssistantId = assistantId;
498 options.Stream = null;
499
500 ClientResult protocolResult = await CreateRunAsync(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions())
501 .ConfigureAwait(false);
502 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
503 }
504
505 /// <summary>
506 /// Begins a new <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
507 /// <see cref="Assistant"/>.
508 /// </summary>
509 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
510 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
511 /// <param name="options"> Additional options for the run. </param>
512 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
513 /// <returns> A new <see cref="ThreadRun"/> instance. </returns>
514 public virtual ClientResult<ThreadRun> CreateRun(string threadId, string assistantId, RunCreationOptions options = null, CancellationToken cancellationToken = default)
515 {
516 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
517 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
518 options ??= new();
519 options.AssistantId = assistantId;
520 options.Stream = null;
521
522 ClientResult protocolResult = CreateRun(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions());
523 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
524 }
525
526 /// <summary>
527 /// Begins a new streaming <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
528 /// <see cref="Assistant"/>.
529 /// </summary>
530 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
531 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
532 /// <param name="options"> Additional options for the run. </param>
533 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
534 public virtual AsyncResultCollection<StreamingUpdate> CreateRunStreamingAsync(
535 string threadId,
536 string assistantId,
537 RunCreationOptions options = null,
538 CancellationToken cancellationToken = default)
539 {
540 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
541 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
542
543 options ??= new();
544 options.AssistantId = assistantId;
545 options.Stream = true;
546
547 async Task<ClientResult> getResultAsync() =>
548 await CreateRunAsync(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions(streaming: true))
549 .ConfigureAwait(false);
550
551 return new AsyncStreamingUpdateCollection(getResultAsync);
552 }
553
554 /// <summary>
555 /// Begins a new streaming <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
556 /// <see cref="Assistant"/>.
557 /// </summary>
558 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
559 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
560 /// <param name="options"> Additional options for the run. </param>
561 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
562 public virtual ResultCollection<StreamingUpdate> CreateRunStreaming(
563 string threadId,
564 string assistantId,
565 RunCreationOptions options = null,
566 CancellationToken cancellationToken = default)
567 {
568 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
569 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
570
571 options ??= new();
572 options.AssistantId = assistantId;
573 options.Stream = true;
574
575 ClientResult getResult() => CreateRun(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions(streaming: true));
576
577 return new StreamingUpdateCollection(getResult);
578 }
579
580 /// <summary>
581 /// Creates a new thread and immediately begins a run against it using the specified <see cref="Assistant"/>.
582 /// </summary>
583 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
584 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
585 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
586 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
587 /// <returns> A new <see cref="ThreadRun"/>. </returns>
588 public virtual async Task<ClientResult<ThreadRun>> CreateThreadAndRunAsync(
589 string assistantId,
590 ThreadCreationOptions threadOptions = null,
591 RunCreationOptions runOptions = null,
592 CancellationToken cancellationToken = default)
593 {
594 runOptions ??= new();
595 runOptions.Stream = null;
596 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
597 ClientResult protocolResult = await CreateThreadAndRunAsync(protocolContent, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
598 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
599 }
600
601 /// <summary>
602 /// Creates a new thread and immediately begins a run against it using the specified <see cref="Assistant"/>.
603 /// </summary>
604 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
605 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
606 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
607 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
608 /// <returns> A new <see cref="ThreadRun"/>. </returns>
609 public virtual ClientResult<ThreadRun> CreateThreadAndRun(
610 string assistantId,
611 ThreadCreationOptions threadOptions = null,
612 RunCreationOptions runOptions = null,
613 CancellationToken cancellationToken = default)
614 {
615 runOptions ??= new();
616 runOptions.Stream = null;
617 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
618 ClientResult protocolResult = CreateThreadAndRun(protocolContent, cancellationToken.ToRequestOptions());
619 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
620 }
621
622 /// <summary>
623 /// Creates a new thread and immediately begins a streaming run against it using the specified <see cref="Assistant"/>.
624 /// </summary>
625 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
626 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
627 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
628 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
629 public virtual AsyncResultCollection<StreamingUpdate> CreateThreadAndRunStreamingAsync(
630 string assistantId,
631 ThreadCreationOptions threadOptions = null,
632 RunCreationOptions runOptions = null,
633 CancellationToken cancellationToken = default)
634 {
635 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
636
637 runOptions ??= new();
638 runOptions.Stream = true;
639 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
640
641 async Task<ClientResult> getResultAsync() =>
642 await CreateThreadAndRunAsync(protocolContent, cancellationToken.ToRequestOptions(streaming: true))
643 .ConfigureAwait(false);
644
645 return new AsyncStreamingUpdateCollection(getResultAsync);
646 }
647
648 /// <summary>
649 /// Creates a new thread and immediately begins a streaming run against it using the specified <see cref="Assistant"/>.
650 /// </summary>
651 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
652 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
653 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
654 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
655 public virtual ResultCollection<StreamingUpdate> CreateThreadAndRunStreaming(
656 string assistantId,
657 ThreadCreationOptions threadOptions = null,
658 RunCreationOptions runOptions = null,
659 CancellationToken cancellationToken = default)
660 {
661 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
662
663 runOptions ??= new();
664 runOptions.Stream = true;
665 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
666
667 ClientResult getResult() => CreateThreadAndRun(protocolContent, cancellationToken.ToRequestOptions(streaming: true));
668
669 return new StreamingUpdateCollection(getResult);
670 }
671
672 /// <summary>
673 /// Returns a collection of <see cref="ThreadRun"/> instances associated with an existing <see cref="AssistantThread"/>.
674 /// </summary>
675 /// <param name="threadId"> The ID of the thread that runs in the list should be associated with. </param>
676 /// <param name="resultOrder">
677 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
678 /// timestamp.
679 /// </param>
680 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
681 /// <returns> A collection of runs that can be enumerated using <c>await foreach</c>. </returns>
682 public virtual AsyncPageableCollection<ThreadRun> GetRunsAsync(
683 string threadId,
684 ListOrder? resultOrder = default,
685 CancellationToken cancellationToken = default)
686 {
687 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
688
689 return CreateAsyncPageable<ThreadRun, InternalListRunsResponse>((continuationToken, pageSize)
690 => GetRunsAsync(threadId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
691 }
692
693 /// <summary>
694 /// Returns a collection of <see cref="ThreadRun"/> instances associated with an existing <see cref="AssistantThread"/>.
695 /// </summary>
696 /// <param name="threadId"> The ID of the thread that runs in the list should be associated with. </param>
697 /// <param name="resultOrder">
698 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
699 /// timestamp.
700 /// </param>
701 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
702 /// <returns> A collection of runs that can be enumerated using <c>foreach</c>. </returns>
703 public virtual PageableCollection<ThreadRun> GetRuns(
704 string threadId,
705 ListOrder? resultOrder = default,
706 CancellationToken cancellationToken = default)
707 {
708 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
709
710 return CreatePageable<ThreadRun, InternalListRunsResponse>((continuationToken, pageSize)
711 => GetRuns(threadId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
712 }
713
714 /// <summary>
715 /// Gets an existing <see cref="ThreadRun"/> from a known <see cref="AssistantThread"/>.
716 /// </summary>
717 /// <param name="threadId"> The ID of the thread to retrieve the run from. </param>
718 /// <param name="runId"> The ID of the run to retrieve. </param>
719 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
720 /// <returns> The existing <see cref="ThreadRun"/> instance. </returns>
721 public virtual async Task<ClientResult<ThreadRun>> GetRunAsync(string threadId, string runId, CancellationToken cancellationToken = default)
722 {
723 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
724 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
725
726 ClientResult protocolResult = await GetRunAsync(threadId, runId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
727 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
728 }
729
730 /// <summary>
731 /// Gets an existing <see cref="ThreadRun"/> from a known <see cref="AssistantThread"/>.
732 /// </summary>
733 /// <param name="threadId"> The ID of the thread to retrieve the run from. </param>
734 /// <param name="runId"> The ID of the run to retrieve. </param>
735 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
736 /// <returns> The existing <see cref="ThreadRun"/> instance. </returns>
737 public virtual ClientResult<ThreadRun> GetRun(string threadId, string runId, CancellationToken cancellationToken = default)
738 {
739 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
740 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
741
742 ClientResult protocolResult = GetRun(threadId, runId, cancellationToken.ToRequestOptions());
743 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
744 }
745
746 /// <summary>
747 /// Submits a collection of required tool call outputs to a run and resumes the run.
748 /// </summary>
749 /// <param name="threadId"> The thread ID of the thread being run. </param>
750 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
751 /// <param name="toolOutputs">
752 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
753 /// </param>
754 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
755 /// <returns> The <see cref="ThreadRun"/>, updated after the submission was processed. </returns>
756 public virtual async Task<ClientResult<ThreadRun>> SubmitToolOutputsToRunAsync(
757 string threadId,
758 string runId,
759 IEnumerable<ToolOutput> toolOutputs,
760 CancellationToken cancellationToken = default)
761 {
762 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
763 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
764
765 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs).ToBinaryContent();
766 ClientResult protocolResult = await SubmitToolOutputsToRunAsync(threadId, runId, content, cancellationToken.ToRequestOptions())
767 .ConfigureAwait(false);
768 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
769 }
770
771 /// <summary>
772 /// Submits a collection of required tool call outputs to a run and resumes the run.
773 /// </summary>
774 /// <param name="threadId"> The thread ID of the thread being run. </param>
775 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
776 /// <param name="toolOutputs">
777 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
778 /// </param>
779 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
780 /// <returns> The <see cref="ThreadRun"/>, updated after the submission was processed. </returns>
781 public virtual ClientResult<ThreadRun> SubmitToolOutputsToRun(
782 string threadId,
783 string runId,
784 IEnumerable<ToolOutput> toolOutputs,
785 CancellationToken cancellationToken = default)
786 {
787 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
788 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
789
790 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs).ToBinaryContent();
791 ClientResult protocolResult = SubmitToolOutputsToRun(threadId, runId, content, cancellationToken.ToRequestOptions());
792 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
793 }
794
795 /// <summary>
796 /// Submits a collection of required tool call outputs to a run and resumes the run with streaming enabled.
797 /// </summary>
798 /// <param name="threadId"> The thread ID of the thread being run. </param>
799 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
800 /// <param name="toolOutputs">
801 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
802 /// </param>
803 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
804 public virtual AsyncResultCollection<StreamingUpdate> SubmitToolOutputsToRunStreamingAsync(
805 string threadId,
806 string runId,
807 IEnumerable<ToolOutput> toolOutputs,
808 CancellationToken cancellationToken = default)
809 {
810 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
811 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
812
813 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs.ToList(), stream: true, null)
814 .ToBinaryContent();
815
816 async Task<ClientResult> getResultAsync() =>
817 await SubmitToolOutputsToRunAsync(threadId, runId, content, cancellationToken.ToRequestOptions(streaming: true))
818 .ConfigureAwait(false);
819
820 return new AsyncStreamingUpdateCollection(getResultAsync);
821 }
822
823 /// <summary>
824 /// Submits a collection of required tool call outputs to a run and resumes the run with streaming enabled.
825 /// </summary>
826 /// <param name="threadId"> The thread ID of the thread being run. </param>
827 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
828 /// <param name="toolOutputs">
829 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
830 /// </param>
831 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
832 public virtual ResultCollection<StreamingUpdate> SubmitToolOutputsToRunStreaming(
833 string threadId,
834 string runId,
835 IEnumerable<ToolOutput> toolOutputs,
836 CancellationToken cancellationToken = default)
837 {
838 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
839 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
840
841 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs.ToList(), stream: true, null)
842 .ToBinaryContent();
843
844 ClientResult getResult() => SubmitToolOutputsToRun(threadId, runId, content, cancellationToken.ToRequestOptions(streaming: true));
845
846 return new StreamingUpdateCollection(getResult);
847 }
848
849 /// <summary>
850 /// Cancels an in-progress <see cref="ThreadRun"/>.
851 /// </summary>
852 /// <param name="threadId"> The ID of the thread associated with the run. </param>
853 /// <param name="runId"> The ID of the run to cancel. </param>
854 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
855 /// <returns> An updated <see cref="ThreadRun"/> instance, reflecting the new status of the run. </returns>
856 public virtual async Task<ClientResult<ThreadRun>> CancelRunAsync(string threadId, string runId, CancellationToken cancellationToken = default)
857 {
858 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
859 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
860
861 ClientResult protocolResult = await CancelRunAsync(threadId, runId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
862 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
863 }
864
865 /// <summary>
866 /// Cancels an in-progress <see cref="ThreadRun"/>.
867 /// </summary>
868 /// <param name="threadId"> The ID of the thread associated with the run. </param>
869 /// <param name="runId"> The ID of the run to cancel. </param>
870 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
871 /// <returns> An updated <see cref="ThreadRun"/> instance, reflecting the new status of the run. </returns>
872 public virtual ClientResult<ThreadRun> CancelRun(string threadId, string runId, CancellationToken cancellationToken = default)
873 {
874 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
875 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
876
877 ClientResult protocolResult = CancelRun(threadId, runId, cancellationToken.ToRequestOptions());
878 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
879 }
880
881 /// <summary>
882 /// Gets a collection of <see cref="RunStep"/> instances associated with a <see cref="ThreadRun"/>.
883 /// </summary>
884 /// <param name="threadId"> The ID of the thread associated with the run. </param>
885 /// <param name="runId"> The ID of the run to list run steps from. </param>
886 /// <param name="resultOrder">
887 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
888 /// timestamp.
889 /// </param>
890 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
891 /// <returns> A collection of run steps that can be enumerated using <c>await foreach</c>. </returns>
892 public virtual AsyncPageableCollection<RunStep> GetRunStepsAsync(
893 string threadId,
894 string runId,
895 ListOrder? resultOrder = default,
896 CancellationToken cancellationToken = default)
897 {
898 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
899 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
900
901 return CreateAsyncPageable<RunStep, InternalListRunStepsResponse>((continuationToken, pageSize)
902 => GetRunStepsAsync(threadId, runId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
903 }
904
905 /// <summary>
906 /// Gets a collection of <see cref="RunStep"/> instances associated with a <see cref="ThreadRun"/>.
907 /// </summary>
908 /// <param name="threadId"> The ID of the thread associated with the run. </param>
909 /// <param name="runId"> The ID of the run to list run steps from. </param>
910 /// <param name="resultOrder">
911 /// The <c>order</c> that results should appear in the list according to their <c>created_at</c>
912 /// timestamp.
913 /// </param>
914 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
915 /// <returns> A collection of run steps that can be enumerated using <c>foreach</c>. </returns>
916 public virtual PageableCollection<RunStep> GetRunSteps(
917 string threadId,
918 string runId,
919 ListOrder? resultOrder = default,
920 CancellationToken cancellationToken = default)
921 {
922 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
923 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
924
925 return CreatePageable<RunStep, InternalListRunStepsResponse>((continuationToken, pageSize)
926 => GetRunSteps(threadId, runId, pageSize, resultOrder?.ToString(), continuationToken, null, cancellationToken.ToRequestOptions()));
927 }
928
929 /// <summary>
930 /// Gets a single run step from a run.
931 /// </summary>
932 /// <param name="threadId"> The ID of the thread associated with the run. </param>
933 /// <param name="runId"> The ID of the run. </param>
934 /// <param name="stepId"> The ID of the run step. </param>
935 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
936 /// <returns> A <see cref="RunStep"/> instance corresponding to the specified step. </returns>
937 public virtual async Task<ClientResult<RunStep>> GetRunStepAsync(string threadId, string runId, string stepId, CancellationToken cancellationToken = default)
938 {
939 ClientResult protocolResult = await GetRunStepAsync(threadId, runId, stepId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
940 return CreateResultFromProtocol(protocolResult, RunStep.FromResponse);
941 }
942
943 /// <summary>
944 /// Gets a single run step from a run.
945 /// </summary>
946 /// <param name="threadId"> The ID of the thread associated with the run. </param>
947 /// <param name="runId"> The ID of the run. </param>
948 /// <param name="stepId"> The ID of the run step. </param>
949 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
950 /// <returns> A <see cref="RunStep"/> instance corresponding to the specified step. </returns>
951 public virtual ClientResult<RunStep> GetRunStep(string threadId, string runId, string stepId, CancellationToken cancellationToken = default)
952 {
953 ClientResult protocolResult = GetRunStep(threadId, runId, stepId, cancellationToken.ToRequestOptions());
954 return CreateResultFromProtocol(protocolResult, RunStep.FromResponse);
955 }
956
957 private static BinaryContent CreateThreadAndRunProtocolContent(
958 string assistantId,
959 ThreadCreationOptions threadOptions,
960 RunCreationOptions runOptions)
961 {
962 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
963 InternalCreateThreadAndRunRequest internalRequest = new(
964 assistantId,
965 threadOptions,
966 runOptions.ModelOverride,
967 runOptions.InstructionsOverride,
968 runOptions.ToolsOverride,
969 // TODO: reconcile exposure of the the two different tool_resources, if needed
970 threadOptions?.ToolResources,
971 runOptions.Metadata,
972 runOptions.Temperature,
973 runOptions.NucleusSamplingFactor,
974 runOptions.Stream,
975 runOptions.MaxPromptTokens,
976 runOptions.MaxCompletionTokens,
977 runOptions.TruncationStrategy,
978 runOptions.ToolConstraint,
979 runOptions.ParallelToolCallsEnabled,
980 runOptions.ResponseFormat,
981 serializedAdditionalRawData: null);
982 return internalRequest.ToBinaryContent();
983 }
984
985 [MethodImpl(MethodImplOptions.AggressiveInlining)]
986 private static ClientResult<T> CreateResultFromProtocol<T>(ClientResult protocolResult, Func<PipelineResponse, T> responseDeserializer)
987 {
988 PipelineResponse pipelineResponse = protocolResult?.GetRawResponse();
989 T deserializedResultValue = responseDeserializer.Invoke(pipelineResponse);
990 return ClientResult.FromValue(deserializedResultValue, pipelineResponse);
991 }
992}
993