openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.0.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/Custom/Assistants/AssistantClient.cs

1280lines · 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;
10
11namespace OpenAI.Assistants;
12
13/// <summary> The service client for OpenAI assistants operations. </summary>
14[Experimental("OPENAI001")]
15[CodeGenClient("Assistants")]
16[CodeGenSuppress("AssistantClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))]
17[CodeGenSuppress("CreateAssistantAsync", typeof(AssistantCreationOptions))]
18[CodeGenSuppress("CreateAssistant", typeof(AssistantCreationOptions))]
19[CodeGenSuppress("GetAssistantAsync", typeof(string))]
20[CodeGenSuppress("GetAssistant", typeof(string))]
21[CodeGenSuppress("ModifyAssistantAsync", typeof(string), typeof(AssistantModificationOptions))]
22[CodeGenSuppress("ModifyAssistant", typeof(string), typeof(AssistantModificationOptions))]
23[CodeGenSuppress("DeleteAssistantAsync", typeof(string))]
24[CodeGenSuppress("DeleteAssistant", typeof(string))]
25[CodeGenSuppress("GetAssistantsAsync", typeof(int?), typeof(AssistantCollectionOrder?), typeof(string), typeof(string))]
26[CodeGenSuppress("GetAssistants", typeof(int?), typeof(AssistantCollectionOrder?), typeof(string), typeof(string))]
27public partial class AssistantClient
28{
29 private readonly InternalAssistantMessageClient _messageSubClient;
30 private readonly InternalAssistantRunClient _runSubClient;
31 private readonly InternalAssistantThreadClient _threadSubClient;
32
33 // CUSTOM: Remove virtual keyword.
34 /// <summary>
35 /// The HTTP pipeline for sending and receiving REST requests and responses.
36 /// </summary>
37 public ClientPipeline Pipeline => _pipeline;
38
39 // CUSTOM: Added as a convenience.
40 /// <summary> Initializes a new instance of <see cref="AssistantClient">. </summary>
41 /// <param name="apiKey"> The API key to authenticate with the service. </param>
42 /// <exception cref="ArgumentNullException"> <paramref name="apiKey"/> is null. </exception>
43 public AssistantClient(string apiKey) : this(new ApiKeyCredential(apiKey), new OpenAIClientOptions())
44 {
45 }
46
47 // CUSTOM:
48 // - Used a custom pipeline.
49 // - Demoted the endpoint parameter to be a property in the options class.
50 /// <summary> Initializes a new instance of <see cref="AssistantClient">. </summary>
51 /// <param name="credential"> The API key to authenticate with the service. </param>
52 /// <exception cref="ArgumentNullException"> <paramref name="credential"/> is null. </exception>
53 public AssistantClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions())
54 {
55 }
56
57 // CUSTOM:
58 // - Used a custom pipeline.
59 // - Demoted the endpoint parameter to be a property in the options class.
60 /// <summary> Initializes a new instance of <see cref="AssistantClient">. </summary>
61 /// <param name="credential"> The API key to authenticate with the service. </param>
62 /// <param name="options"> The options to configure the client. </param>
63 /// <exception cref="ArgumentNullException"> <paramref name="credential"/> is null. </exception>
64 public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options)
65 {
66 Argument.AssertNotNull(credential, nameof(credential));
67 options ??= new OpenAIClientOptions();
68
69 _pipeline = OpenAIClient.CreatePipeline(credential, options);
70 _endpoint = OpenAIClient.GetEndpoint(options);
71 _messageSubClient = new(_pipeline, options);
72 _runSubClient = new(_pipeline, options);
73 _threadSubClient = new(_pipeline, options);
74 }
75
76 // CUSTOM:
77 // - Used a custom pipeline.
78 // - Demoted the endpoint parameter to be a property in the options class.
79 // - Made protected.
80 /// <summary> Initializes a new instance of <see cref="AssistantClient">. </summary>
81 /// <param name="pipeline"> The HTTP pipeline to send and receive REST requests and responses. </param>
82 /// <param name="options"> The options to configure the client. </param>
83 /// <exception cref="ArgumentNullException"> <paramref name="pipeline"/> is null. </exception>
84 protected internal AssistantClient(ClientPipeline pipeline, OpenAIClientOptions options)
85 {
86 Argument.AssertNotNull(pipeline, nameof(pipeline));
87 options ??= new OpenAIClientOptions();
88
89 _pipeline = pipeline;
90 _endpoint = OpenAIClient.GetEndpoint(options);
91 _messageSubClient = new(_pipeline, options);
92 _runSubClient = new(_pipeline, options);
93 _threadSubClient = new(_pipeline, options);
94 }
95
96 /// <summary> Creates a new assistant. </summary>
97 /// <param name="model"> The default model that the assistant should use. </param>
98 /// <param name="options"> The additional <see cref="AssistantCreationOptions"/> to use. </param>
99 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
100 /// <exception cref="ArgumentException"> <paramref name="model"/> is null or empty. </exception>
101 public virtual async Task<ClientResult<Assistant>> CreateAssistantAsync(string model, AssistantCreationOptions options = null, CancellationToken cancellationToken = default)
102 {
103 Argument.AssertNotNullOrEmpty(model, nameof(model));
104 options ??= new();
105 options.Model = model;
106
107 ClientResult protocolResult = await CreateAssistantAsync(options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
108 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
109 }
110
111 /// <summary> Creates a new assistant. </summary>
112 /// <param name="model"> The default model that the assistant should use. </param>
113 /// <param name="options"> The additional <see cref="AssistantCreationOptions"/> to use. </param>
114 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
115 /// <exception cref="ArgumentException"> <paramref name="model"/> is null or empty. </exception>
116 public virtual ClientResult<Assistant> CreateAssistant(string model, AssistantCreationOptions options = null, CancellationToken cancellationToken = default)
117 {
118 Argument.AssertNotNullOrEmpty(model, nameof(model));
119 options ??= new();
120 options.Model = model;
121
122 ClientResult protocolResult = CreateAssistant(options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
123 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
124 }
125
126 /// <summary>
127 /// Gets a page collection holding <see cref="Assistant"/> instances.
128 /// </summary>
129 /// <param name="options"> Options describing the collection to return. </param>
130 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
131 /// <returns> A collection of <see cref="Assistant"/>. </returns>
132 public virtual AsyncCollectionResult<Assistant> GetAssistantsAsync(
133 AssistantCollectionOptions options = default,
134 CancellationToken cancellationToken = default)
135 {
136 AsyncCollectionResult result = GetAssistantsAsync(options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
137
138 if (result is not AsyncCollectionResult<Assistant> assistantCollection)
139 {
140 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<Assistant>'.");
141 }
142
143 return assistantCollection;
144 }
145
146 /// <summary>
147 /// Rehydrates a page collection holding <see cref="Assistant"/> instances from a page token.
148 /// </summary>
149 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
150 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
151 /// <returns> A collection of <see cref="Assistant"/>. </returns>
152 public virtual AsyncCollectionResult<Assistant> GetAssistantsAsync(
153 ContinuationToken firstPageToken,
154 CancellationToken cancellationToken = default)
155 {
156 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
157
158 AssistantCollectionPageToken pageToken = AssistantCollectionPageToken.FromToken(firstPageToken);
159 AsyncCollectionResult result = GetAssistantsAsync(pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken.Before, cancellationToken.ToRequestOptions());
160
161 if (result is not AsyncCollectionResult<Assistant> assistantCollection)
162 {
163 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<Assistant>'.");
164 }
165
166 return assistantCollection;
167 }
168
169 /// <summary>
170 /// Gets a page collection holding <see cref="Assistant"/> instances.
171 /// </summary>
172 /// <param name="options"> Options describing the collection to return. </param>
173 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
174 /// <returns> A collection of <see cref="Assistant"/>. </returns>
175 public virtual CollectionResult<Assistant> GetAssistants(
176 AssistantCollectionOptions options = default,
177 CancellationToken cancellationToken = default)
178 {
179 CollectionResult result = GetAssistants(options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
180
181 if (result is not CollectionResult<Assistant> assistantCollection)
182 {
183 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<Assistant>'.");
184 }
185
186 return assistantCollection;
187 }
188
189 /// <summary>
190 /// Rehydrates a page collection holding <see cref="Assistant"/> instances from a page token.
191 /// </summary>
192 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
193 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
194 /// <returns> A collection of <see cref="Assistant"/>. </returns>
195 public virtual CollectionResult<Assistant> GetAssistants(
196 ContinuationToken firstPageToken,
197 CancellationToken cancellationToken = default)
198 {
199 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
200
201 AssistantCollectionPageToken pageToken = AssistantCollectionPageToken.FromToken(firstPageToken);
202 CollectionResult result = GetAssistants(pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken.Before, cancellationToken.ToRequestOptions());
203
204 if (result is not CollectionResult<Assistant> assistantCollection)
205 {
206 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<Assistant>'.");
207 }
208
209 return assistantCollection;
210 }
211
212 /// <summary>
213 /// Gets an instance representing an existing <see cref="Assistant"/> based on its ID.
214 /// </summary>
215 /// <param name="assistantId"> The ID of the Assistant to retrieve. </param>
216 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
217 /// <returns>An <see cref="Assistant"/> instance representing the state of the Assistant with the provided ID.</returns>
218 public virtual async Task<ClientResult<Assistant>> GetAssistantAsync(string assistantId, CancellationToken cancellationToken = default)
219 {
220 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
221
222 ClientResult protocolResult = await GetAssistantAsync(assistantId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
223 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
224 }
225
226 /// <summary>
227 /// Gets an instance representing an existing <see cref="Assistant"/> based on its ID.
228 /// </summary>
229 /// <param name="assistantId"> The ID of the Assistant to retrieve. </param>
230 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
231 /// <returns>An <see cref="Assistant"/> instance representing the state of the Assistant with the provided ID.</returns>
232 public virtual ClientResult<Assistant> GetAssistant(string assistantId, CancellationToken cancellationToken = default)
233 {
234 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
235
236 ClientResult protocolResult = GetAssistant(assistantId, cancellationToken.ToRequestOptions());
237 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
238 }
239
240 /// <summary>
241 /// Modifies an existing <see cref="Assistant"/>.
242 /// </summary>
243 /// <param name="assistantId"> The ID of the Assistant to retrieve. </param>
244 /// <param name="options"> The new options to apply to the existing Assistant. </param>
245 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
246 /// <returns> An updated <see cref="Assistant"/> instance representing the state of the Assistant with the provided ID. </returns>
247 public virtual async Task<ClientResult<Assistant>> ModifyAssistantAsync(string assistantId, AssistantModificationOptions options, CancellationToken cancellationToken = default)
248 {
249 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
250 Argument.AssertNotNull(options, nameof(options));
251
252 using BinaryContent content = options.ToBinaryContent();
253 ClientResult protocolResult
254 = await ModifyAssistantAsync(assistantId, content, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
255 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
256 }
257
258 /// <summary>
259 /// Modifies an existing <see cref="Assistant"/>.
260 /// </summary>
261 /// <param name="assistantId"> The ID of the Assistant to retrieve. </param>
262 /// <param name="options"> The new options to apply to the existing Assistant. </param>
263 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
264 /// <returns> An updated <see cref="Assistant"/> instance representing the state of the Assistant with the provided ID. </returns>
265 public virtual ClientResult<Assistant> ModifyAssistant(string assistantId, AssistantModificationOptions options, CancellationToken cancellationToken = default)
266 {
267 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
268 Argument.AssertNotNull(options, nameof(options));
269
270 using BinaryContent content = options.ToBinaryContent();
271 ClientResult protocolResult = ModifyAssistant(assistantId, content, null);
272 return CreateResultFromProtocol(protocolResult, Assistant.FromResponse);
273 }
274
275 /// <summary>
276 /// Deletes an existing <see cref="Assistant"/>.
277 /// </summary>
278 /// <param name="assistantId"> The ID of the assistant to delete. </param>
279 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
280 /// <returns> A <see cref="AssistantDeletionResult"/> instance. </returns>
281 public virtual async Task<ClientResult<AssistantDeletionResult>> DeleteAssistantAsync(string assistantId, CancellationToken cancellationToken = default)
282 {
283 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
284
285 ClientResult protocolResult = await DeleteAssistantAsync(assistantId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
286 return CreateResultFromProtocol(protocolResult, response
287 => AssistantDeletionResult.FromResponse(response));
288 }
289
290 /// <summary>
291 /// Deletes an existing <see cref="Assistant"/>.
292 /// </summary>
293 /// <param name="assistantId"> The ID of the assistant to delete. </param>
294 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
295 /// <returns> A <see cref="AssistantDeletionResult"/> instance. </returns>
296 public virtual ClientResult<AssistantDeletionResult> DeleteAssistant(string assistantId, CancellationToken cancellationToken = default)
297 {
298 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
299
300 ClientResult protocolResult = DeleteAssistant(assistantId, cancellationToken.ToRequestOptions());
301 return CreateResultFromProtocol(protocolResult, response
302 => AssistantDeletionResult.FromResponse(response));
303 }
304
305 /// <summary>
306 /// Creates a new <see cref="AssistantThread"/>.
307 /// </summary>
308 /// <param name="options"> Additional options to use when creating the thread. </param>
309 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
310 /// <returns> A new thread. </returns>
311 public virtual async Task<ClientResult<AssistantThread>> CreateThreadAsync(ThreadCreationOptions options = null, CancellationToken cancellationToken = default)
312 {
313 ClientResult protocolResult = await CreateThreadAsync(options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
314 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
315 }
316
317 /// <summary>
318 /// Creates a new <see cref="AssistantThread"/>.
319 /// </summary>
320 /// <param name="options"> Additional options to use when creating the thread. </param>
321 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
322 /// <returns> A new thread. </returns>
323 public virtual ClientResult<AssistantThread> CreateThread(ThreadCreationOptions options = null, CancellationToken cancellationToken = default)
324 {
325 ClientResult protocolResult = CreateThread(options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
326 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
327 }
328
329 /// <summary>
330 /// Gets an existing <see cref="AssistantThread"/>, retrieved via a known ID.
331 /// </summary>
332 /// <param name="threadId"> The ID of the thread to retrieve. </param>
333 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
334 /// <returns> The existing thread instance. </returns>
335 public virtual async Task<ClientResult<AssistantThread>> GetThreadAsync(string threadId, CancellationToken cancellationToken = default)
336 {
337 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
338
339 ClientResult protocolResult = await GetThreadAsync(threadId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
340 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
341 }
342
343 /// <summary>
344 /// Gets an existing <see cref="AssistantThread"/>, retrieved via a known ID.
345 /// </summary>
346 /// <param name="threadId"> The ID of the thread to retrieve. </param>
347 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
348 /// <returns> The existing thread instance. </returns>
349 public virtual ClientResult<AssistantThread> GetThread(string threadId, CancellationToken cancellationToken = default)
350 {
351 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
352
353 ClientResult protocolResult = GetThread(threadId, cancellationToken.ToRequestOptions());
354 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
355 }
356
357 /// <summary>
358 /// Modifies an existing <see cref="AssistantThread"/>.
359 /// </summary>
360 /// <param name="threadId"> The ID of the thread to modify. </param>
361 /// <param name="options"> The modifications to apply to the thread. </param>
362 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
363 /// <returns> The updated <see cref="AssistantThread"/> instance. </returns>
364 public virtual async Task<ClientResult<AssistantThread>> ModifyThreadAsync(string threadId, ThreadModificationOptions options, CancellationToken cancellationToken = default)
365 {
366 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
367 Argument.AssertNotNull(options, nameof(options));
368
369 ClientResult protocolResult = await ModifyThreadAsync(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions()).ConfigureAwait(false);
370 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
371 }
372
373 /// <summary>
374 /// Modifies an existing <see cref="AssistantThread"/>.
375 /// </summary>
376 /// <param name="threadId"> The ID of the thread to modify. </param>
377 /// <param name="options"> The modifications to apply to the thread. </param>
378 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
379 /// <returns> The updated <see cref="AssistantThread"/> instance. </returns>
380 public virtual ClientResult<AssistantThread> ModifyThread(string threadId, ThreadModificationOptions options, CancellationToken cancellationToken = default)
381 {
382 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
383 Argument.AssertNotNull(options, nameof(options));
384
385 ClientResult protocolResult = ModifyThread(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
386 return CreateResultFromProtocol(protocolResult, AssistantThread.FromResponse);
387 }
388
389 /// <summary>
390 /// Deletes an existing <see cref="AssistantThread"/>.
391 /// </summary>
392 /// <param name="threadId"> The ID of the thread to delete. </param>
393 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
394 /// <returns> A <see cref="ThreadDeletionResult"/> instance. </returns>
395 public virtual async Task<ClientResult<ThreadDeletionResult>> DeleteThreadAsync(string threadId, CancellationToken cancellationToken = default)
396 {
397 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
398
399 ClientResult protocolResult = await DeleteThreadAsync(threadId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
400 return CreateResultFromProtocol(protocolResult, response
401 => ThreadDeletionResult.FromResponse(response));
402 }
403
404 /// <summary>
405 /// Deletes an existing <see cref="AssistantThread"/>.
406 /// </summary>
407 /// <param name="threadId"> The ID of the thread to delete. </param>
408 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
409 /// <returns> A <see cref="ThreadDeletionResult"/> instance. </returns>
410 public virtual ClientResult<ThreadDeletionResult> DeleteThread(string threadId, CancellationToken cancellationToken = default)
411 {
412 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
413
414 ClientResult protocolResult = DeleteThread(threadId, cancellationToken.ToRequestOptions());
415 return CreateResultFromProtocol(protocolResult, response
416 => ThreadDeletionResult.FromResponse(response));
417 }
418
419 /// <summary>
420 /// Creates a new <see cref="ThreadMessage"/> on an existing <see cref="AssistantThread"/>.
421 /// </summary>
422 /// <param name="threadId"> The ID of the thread to associate the new message with. </param>
423 /// <param name="role"> The role to associate with the new message. </param>
424 /// <param name="content"> The collection of <see cref="MessageContent"/> items for the message. </param>
425 /// <param name="options"> Additional options to apply to the new message. </param>
426 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
427 /// <returns> A new <see cref="ThreadMessage"/>. </returns>
428 public virtual async Task<ClientResult<ThreadMessage>> CreateMessageAsync(
429 string threadId,
430 MessageRole role,
431 IEnumerable<MessageContent> content,
432 MessageCreationOptions options = null,
433 CancellationToken cancellationToken = default)
434 {
435 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
436 options ??= new();
437 options.Role = role;
438 options.Content.Clear();
439 foreach (MessageContent contentItem in content)
440 {
441 options.Content.Add(contentItem);
442 }
443
444 ClientResult protocolResult = await CreateMessageAsync(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions())
445 .ConfigureAwait(false);
446 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
447 }
448
449 /// <summary>
450 /// Creates a new <see cref="ThreadMessage"/> on an existing <see cref="AssistantThread"/>.
451 /// </summary>
452 /// <param name="threadId"> The ID of the thread to associate the new message with. </param>
453 /// <param name="role"> The role to associate with the new message. </param>
454 /// <param name="content"> The collection of <see cref="MessageContent"/> items for the message. </param>
455 /// <param name="options"> Additional options to apply to the new message. </param>
456 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
457 /// <returns> A new <see cref="ThreadMessage"/>. </returns>
458 public virtual ClientResult<ThreadMessage> CreateMessage(
459 string threadId,
460 MessageRole role,
461 IEnumerable<MessageContent> content,
462 MessageCreationOptions options = null,
463 CancellationToken cancellationToken = default)
464 {
465 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
466 options ??= new();
467 options.Role = role;
468 options.Content.Clear();
469 foreach (MessageContent contentItem in content)
470 {
471 options.Content.Add(contentItem);
472 }
473
474 ClientResult protocolResult = CreateMessage(threadId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
475 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
476 }
477
478 /// <summary>
479 /// Gets a page collection of <see cref="ThreadMessage"/> instances from an existing <see cref="AssistantThread"/>.
480 /// </summary>
481 /// <param name="threadId"> The ID of the thread to list messages from. </param>
482 /// <param name="options"> Options describing the collection to return. </param>
483 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
484 /// <returns> A collection of <see cref="ThreadMessage"/>. </returns>
485 public virtual AsyncCollectionResult<ThreadMessage> GetMessagesAsync(
486 string threadId,
487 MessageCollectionOptions options = default,
488 CancellationToken cancellationToken = default)
489 {
490 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
491
492 AsyncCollectionResult result = GetMessagesAsync(threadId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
493
494 if (result is not AsyncCollectionResult<ThreadMessage> collection)
495 {
496 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<ThreadMessage>'.");
497 }
498
499 return collection;
500 }
501
502 /// <summary>
503 /// Rehydrates a page collection of <see cref="ThreadMessage"/> instances from a page token.
504 /// </summary>
505 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
506 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
507 /// <returns> A collection of <see cref="ThreadMessage"/>. </returns>
508 public virtual AsyncCollectionResult<ThreadMessage> GetMessagesAsync(
509 ContinuationToken firstPageToken,
510 CancellationToken cancellationToken = default)
511 {
512 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
513
514 MessageCollectionPageToken pageToken = MessageCollectionPageToken.FromToken(firstPageToken);
515 AsyncCollectionResult result = GetMessagesAsync(pageToken?.ThreadId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
516
517 if (result is not AsyncCollectionResult<ThreadMessage> collection)
518 {
519 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<ThreadMessage>'.");
520 }
521
522 return collection;
523 }
524
525 /// <summary>
526 /// Gets a page collection holding <see cref="ThreadMessage"/> instances from an existing <see cref="AssistantThread"/>.
527 /// </summary>
528 /// <param name="threadId"> The ID of the thread to list messages from. </param>
529 /// <param name="options"> Options describing the collection to return. </param>
530 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
531 /// <returns> A collection of <see cref="ThreadMessage"/>. </returns>
532 public virtual CollectionResult<ThreadMessage> GetMessages(
533 string threadId,
534 MessageCollectionOptions options = default,
535 CancellationToken cancellationToken = default)
536 {
537 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
538
539 CollectionResult result = GetMessages(threadId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
540
541 if (result is not CollectionResult<ThreadMessage> collection)
542 {
543 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<ThreadMessage>'.");
544 }
545
546 return collection;
547 }
548
549 /// <summary>
550 /// Rehydrates a page collection holding <see cref="ThreadMessage"/> instances from a page token.
551 /// </summary>
552 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
553 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
554 /// <returns> A collection of <see cref="ThreadMessage"/>. </returns>
555 public virtual CollectionResult<ThreadMessage> GetMessages(
556 ContinuationToken firstPageToken,
557 CancellationToken cancellationToken = default)
558 {
559 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
560
561 MessageCollectionPageToken pageToken = MessageCollectionPageToken.FromToken(firstPageToken);
562 CollectionResult result = GetMessages(pageToken?.ThreadId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
563
564 if (result is not CollectionResult<ThreadMessage> collection)
565 {
566 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<ThreadMessage>'.");
567 }
568
569 return collection;
570
571 }
572
573 /// <summary>
574 /// Gets an existing <see cref="ThreadMessage"/> from a known <see cref="AssistantThread"/>.
575 /// </summary>
576 /// <param name="threadId"> The ID of the thread to retrieve the message from. </param>
577 /// <param name="messageId"> The ID of the message to retrieve. </param>
578 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
579 /// <returns> The existing <see cref="ThreadMessage"/> instance. </returns>
580 public virtual async Task<ClientResult<ThreadMessage>> GetMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default)
581 {
582 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
583 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
584
585 ClientResult protocolResult = await GetMessageAsync(threadId, messageId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
586 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
587 }
588
589 /// <summary>
590 /// Gets an existing <see cref="ThreadMessage"/> from a known <see cref="AssistantThread"/>.
591 /// </summary>
592 /// <param name="threadId"> The ID of the thread to retrieve the message from. </param>
593 /// <param name="messageId"> The ID of the message to retrieve. </param>
594 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
595 /// <returns> The existing <see cref="ThreadMessage"/> instance. </returns>
596 public virtual ClientResult<ThreadMessage> GetMessage(string threadId, string messageId, CancellationToken cancellationToken = default)
597 {
598 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
599 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
600
601 ClientResult protocolResult = GetMessage(threadId, messageId, cancellationToken.ToRequestOptions());
602 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
603 }
604
605 /// <summary>
606 /// Modifies an existing <see cref="ThreadMessage"/>.
607 /// </summary>
608 /// <param name="threadId"> The ID of the thread associated with the message to modify. </param>
609 /// <param name="messageId"> The ID of the message to modify. </param>
610 /// <param name="options"> The changes to apply to the message. </param>
611 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
612 /// <returns> The updated <see cref="ThreadMessage"/>. </returns>
613 public virtual async Task<ClientResult<ThreadMessage>> ModifyMessageAsync(string threadId, string messageId, MessageModificationOptions options, CancellationToken cancellationToken = default)
614 {
615 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
616 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
617 Argument.AssertNotNull(options, nameof(options));
618
619 ClientResult protocolResult = await ModifyMessageAsync(threadId, messageId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions())
620 .ConfigureAwait(false);
621 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
622 }
623
624 /// <summary>
625 /// Modifies an existing <see cref="ThreadMessage"/>.
626 /// </summary>
627 /// <param name="threadId"> The ID of the thread associated with the message to modify. </param>
628 /// <param name="messageId"> The ID of the message to modify. </param>
629 /// <param name="options"> The changes to apply to the message. </param>
630 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
631 /// <returns> The updated <see cref="ThreadMessage"/>. </returns>
632 public virtual ClientResult<ThreadMessage> ModifyMessage(string threadId, string messageId, MessageModificationOptions options, CancellationToken cancellationToken = default)
633 {
634 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
635 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
636 Argument.AssertNotNull(options, nameof(options));
637
638 ClientResult protocolResult = ModifyMessage(threadId, messageId, options?.ToBinaryContent(), cancellationToken.ToRequestOptions());
639 return CreateResultFromProtocol(protocolResult, ThreadMessage.FromResponse);
640 }
641
642 /// <summary>
643 /// Deletes an existing <see cref="ThreadMessage"/>.
644 /// </summary>
645 /// <param name="threadId"> The ID of the thread associated with the message. </param>
646 /// <param name="messageId"> The ID of the message. </param>
647 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
648 /// <returns> A <see cref="MessageDeletionResult"/> instance. </returns>
649 public virtual async Task<ClientResult<MessageDeletionResult>> DeleteMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default)
650 {
651 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
652 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
653
654 ClientResult protocolResult = await DeleteMessageAsync(threadId, messageId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
655 return CreateResultFromProtocol(protocolResult, response =>
656 MessageDeletionResult.FromResponse(response));
657 }
658
659 /// <summary>
660 /// Deletes an existing <see cref="ThreadMessage"/>.
661 /// </summary>
662 /// <param name="threadId"> The ID of the thread associated with the message. </param>
663 /// <param name="messageId"> The ID of the message. </param>
664 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
665 /// <returns> A <see cref="MessageDeletionResult"/> instance. </returns>
666 public virtual ClientResult<MessageDeletionResult> DeleteMessage(string threadId, string messageId, CancellationToken cancellationToken = default)
667 {
668 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
669 Argument.AssertNotNullOrEmpty(messageId, nameof(messageId));
670
671 ClientResult protocolResult = DeleteMessage(threadId, messageId, cancellationToken.ToRequestOptions());
672 return CreateResultFromProtocol(protocolResult, response =>
673 MessageDeletionResult.FromResponse(response));
674 }
675
676 /// <summary>
677 /// Begins a new <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
678 /// <see cref="Assistant"/>.
679 /// </summary>
680 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
681 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
682 /// <param name="options"> Additional options for the run. </param>
683 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
684 /// <returns> A new <see cref="ThreadRun"/> instance. </returns>
685 public virtual async Task<ClientResult<ThreadRun>> CreateRunAsync(string threadId, string assistantId, RunCreationOptions options = null, CancellationToken cancellationToken = default)
686 {
687 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
688 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
689 options ??= new();
690 options.AssistantId = assistantId;
691 options.Stream = null;
692
693 ClientResult protocolResult = await CreateRunAsync(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions())
694 .ConfigureAwait(false);
695 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
696 }
697
698 /// <summary>
699 /// Begins a new <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
700 /// <see cref="Assistant"/>.
701 /// </summary>
702 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
703 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
704 /// <param name="options"> Additional options for the run. </param>
705 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
706 /// <returns> A new <see cref="ThreadRun"/> instance. </returns>
707 public virtual ClientResult<ThreadRun> CreateRun(string threadId, string assistantId, RunCreationOptions options = null, CancellationToken cancellationToken = default)
708 {
709 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
710 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
711 options ??= new();
712 options.AssistantId = assistantId;
713 options.Stream = null;
714
715 ClientResult protocolResult = CreateRun(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions());
716 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
717 }
718
719 /// <summary>
720 /// Begins a new streaming <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
721 /// <see cref="Assistant"/>.
722 /// </summary>
723 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
724 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
725 /// <param name="options"> Additional options for the run. </param>
726 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
727 public virtual AsyncCollectionResult<StreamingUpdate> CreateRunStreamingAsync(
728 string threadId,
729 string assistantId,
730 RunCreationOptions options = null,
731 CancellationToken cancellationToken = default)
732 {
733 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
734 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
735
736 options ??= new();
737 options.AssistantId = assistantId;
738 options.Stream = true;
739
740 async Task<ClientResult> sendRequestAsync() =>
741 await CreateRunAsync(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions(streaming: true))
742 .ConfigureAwait(false);
743
744 return new AsyncStreamingUpdateCollection(sendRequestAsync, cancellationToken);
745 }
746
747 /// <summary>
748 /// Begins a new streaming <see cref="ThreadRun"/> that evaluates a <see cref="AssistantThread"/> using a specified
749 /// <see cref="Assistant"/>.
750 /// </summary>
751 /// <param name="threadId"> The ID of the thread that the run should evaluate. </param>
752 /// <param name="assistantId"> The ID of the assistant that should be used when evaluating the thread. </param>
753 /// <param name="options"> Additional options for the run. </param>
754 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
755 public virtual CollectionResult<StreamingUpdate> CreateRunStreaming(
756 string threadId,
757 string assistantId,
758 RunCreationOptions options = null,
759 CancellationToken cancellationToken = default)
760 {
761 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
762 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
763
764 options ??= new();
765 options.AssistantId = assistantId;
766 options.Stream = true;
767
768 ClientResult sendRequest() => CreateRun(threadId, options.ToBinaryContent(), cancellationToken.ToRequestOptions(streaming: true));
769 return new StreamingUpdateCollection(sendRequest, cancellationToken);
770 }
771
772 /// <summary>
773 /// Creates a new thread and immediately begins a run against it using the specified <see cref="Assistant"/>.
774 /// </summary>
775 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
776 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
777 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
778 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
779 /// <returns> A new <see cref="ThreadRun"/>. </returns>
780 public virtual async Task<ClientResult<ThreadRun>> CreateThreadAndRunAsync(
781 string assistantId,
782 ThreadCreationOptions threadOptions = null,
783 RunCreationOptions runOptions = null,
784 CancellationToken cancellationToken = default)
785 {
786 runOptions ??= new();
787 runOptions.Stream = null;
788 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
789 ClientResult protocolResult = await CreateThreadAndRunAsync(protocolContent, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
790 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
791 }
792
793 /// <summary>
794 /// Creates a new thread and immediately begins a run against it using the specified <see cref="Assistant"/>.
795 /// </summary>
796 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
797 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
798 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
799 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
800 /// <returns> A new <see cref="ThreadRun"/>. </returns>
801 public virtual ClientResult<ThreadRun> CreateThreadAndRun(
802 string assistantId,
803 ThreadCreationOptions threadOptions = null,
804 RunCreationOptions runOptions = null,
805 CancellationToken cancellationToken = default)
806 {
807 runOptions ??= new();
808 runOptions.Stream = null;
809 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
810 ClientResult protocolResult = CreateThreadAndRun(protocolContent, cancellationToken.ToRequestOptions());
811 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
812 }
813
814 /// <summary>
815 /// Creates a new thread and immediately begins a streaming run against it using the specified <see cref="Assistant"/>.
816 /// </summary>
817 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
818 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
819 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
820 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
821 public virtual AsyncCollectionResult<StreamingUpdate> CreateThreadAndRunStreamingAsync(
822 string assistantId,
823 ThreadCreationOptions threadOptions = null,
824 RunCreationOptions runOptions = null,
825 CancellationToken cancellationToken = default)
826 {
827 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
828
829 runOptions ??= new();
830 runOptions.Stream = true;
831 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
832
833 async Task<ClientResult> sendRequestAsync() =>
834 await CreateThreadAndRunAsync(protocolContent, cancellationToken.ToRequestOptions(streaming: true))
835 .ConfigureAwait(false);
836
837 return new AsyncStreamingUpdateCollection(sendRequestAsync, cancellationToken);
838 }
839
840 /// <summary>
841 /// Creates a new thread and immediately begins a streaming run against it using the specified <see cref="Assistant"/>.
842 /// </summary>
843 /// <param name="assistantId"> The ID of the assistant that the new run should use. </param>
844 /// <param name="threadOptions"> Options for the new thread that will be created. </param>
845 /// <param name="runOptions"> Additional options to apply to the run that will begin. </param>
846 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
847 public virtual CollectionResult<StreamingUpdate> CreateThreadAndRunStreaming(
848 string assistantId,
849 ThreadCreationOptions threadOptions = null,
850 RunCreationOptions runOptions = null,
851 CancellationToken cancellationToken = default)
852 {
853 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
854
855 runOptions ??= new();
856 runOptions.Stream = true;
857 BinaryContent protocolContent = CreateThreadAndRunProtocolContent(assistantId, threadOptions, runOptions);
858
859 ClientResult sendRequest() => CreateThreadAndRun(protocolContent, cancellationToken.ToRequestOptions(streaming: true));
860 return new StreamingUpdateCollection(sendRequest, cancellationToken);
861 }
862
863 /// <summary>
864 /// Gets a page collection holding <see cref="ThreadRun"/> instances associated with an existing <see cref="AssistantThread"/>.
865 /// </summary>
866 /// <param name="threadId"> The ID of the thread that runs in the list should be associated with. </param>
867 /// <param name="options"> Options describing the collection to return. </param>
868 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
869 /// <returns> A collection of <see cref="ThreadRun"/>. </returns>
870 public virtual AsyncCollectionResult<ThreadRun> GetRunsAsync(
871 string threadId,
872 RunCollectionOptions options = default,
873 CancellationToken cancellationToken = default)
874 {
875 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
876
877 AsyncCollectionResult result = GetRunsAsync(threadId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
878
879 if (result is not AsyncCollectionResult<ThreadRun> collection)
880 {
881 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<ThreadRun>'.");
882 }
883
884 return collection;
885 }
886
887 /// <summary>
888 /// Rehydrates a page collection holding <see cref="ThreadRun"/> instances from a page token.
889 /// </summary>
890 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
891 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
892 /// <returns> A collection of <see cref="ThreadRun"/>. </returns>
893 public virtual AsyncCollectionResult<ThreadRun> GetRunsAsync(
894 ContinuationToken firstPageToken,
895 CancellationToken cancellationToken = default)
896 {
897 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
898
899 RunCollectionPageToken pageToken = RunCollectionPageToken.FromToken(firstPageToken);
900 AsyncCollectionResult result = GetRunsAsync(pageToken?.ThreadId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
901
902 if (result is not AsyncCollectionResult<ThreadRun> collection)
903 {
904 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<ThreadRun>'.");
905 }
906
907 return collection;
908 }
909
910 /// <summary>
911 /// Gets a page collection holding <see cref="ThreadRun"/> instances associated with an existing <see cref="AssistantThread"/>.
912 /// </summary>
913 /// <param name="threadId"> The ID of the thread that runs in the list should be associated with. </param>
914 /// <param name="options"> Options describing the collection to return. </param>
915 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
916 /// <returns> A collection of <see cref="ThreadRun"/>. </returns>
917 public virtual CollectionResult<ThreadRun> GetRuns(
918 string threadId,
919 RunCollectionOptions options = default,
920 CancellationToken cancellationToken = default)
921 {
922 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
923
924 CollectionResult result = GetRuns(threadId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
925
926 if (result is not CollectionResult<ThreadRun> collection)
927 {
928 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<ThreadRun>'.");
929 }
930
931 return collection;
932 }
933
934 /// <summary>
935 /// Rehydrates a page collection holding <see cref="ThreadRun"/> instances from a page token.
936 /// </summary>
937 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
938 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
939 /// <returns> A collection of <see cref="ThreadRun"/>. </returns>
940 public virtual CollectionResult<ThreadRun> GetRuns(
941 ContinuationToken firstPageToken,
942 CancellationToken cancellationToken = default)
943 {
944 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
945
946 RunCollectionPageToken pageToken = RunCollectionPageToken.FromToken(firstPageToken);
947 CollectionResult result = GetRuns(pageToken?.ThreadId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
948
949 if (result is not CollectionResult<ThreadRun> collection)
950 {
951 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<ThreadRun>'.");
952 }
953
954 return collection;
955 }
956
957 /// <summary>
958 /// Gets an existing <see cref="ThreadRun"/> from a known <see cref="AssistantThread"/>.
959 /// </summary>
960 /// <param name="threadId"> The ID of the thread to retrieve the run from. </param>
961 /// <param name="runId"> The ID of the run to retrieve. </param>
962 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
963 /// <returns> The existing <see cref="ThreadRun"/> instance. </returns>
964 public virtual async Task<ClientResult<ThreadRun>> GetRunAsync(string threadId, string runId, CancellationToken cancellationToken = default)
965 {
966 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
967 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
968
969 ClientResult protocolResult = await GetRunAsync(threadId, runId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
970 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
971 }
972
973 /// <summary>
974 /// Gets an existing <see cref="ThreadRun"/> from a known <see cref="AssistantThread"/>.
975 /// </summary>
976 /// <param name="threadId"> The ID of the thread to retrieve the run from. </param>
977 /// <param name="runId"> The ID of the run to retrieve. </param>
978 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
979 /// <returns> The existing <see cref="ThreadRun"/> instance. </returns>
980 public virtual ClientResult<ThreadRun> GetRun(string threadId, string runId, CancellationToken cancellationToken = default)
981 {
982 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
983 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
984
985 ClientResult protocolResult = GetRun(threadId, runId, cancellationToken.ToRequestOptions());
986 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
987 }
988
989 /// <summary>
990 /// Submits a collection of required tool call outputs to a run and resumes the run.
991 /// </summary>
992 /// <param name="threadId"> The thread ID of the thread being run. </param>
993 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
994 /// <param name="toolOutputs">
995 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
996 /// </param>
997 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
998 /// <returns> The <see cref="ThreadRun"/>, updated after the submission was processed. </returns>
999 public virtual async Task<ClientResult<ThreadRun>> SubmitToolOutputsToRunAsync(
1000 string threadId,
1001 string runId,
1002 IEnumerable<ToolOutput> toolOutputs,
1003 CancellationToken cancellationToken = default)
1004 {
1005 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1006 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1007
1008 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs).ToBinaryContent();
1009 ClientResult protocolResult = await SubmitToolOutputsToRunAsync(threadId, runId, content, cancellationToken.ToRequestOptions())
1010 .ConfigureAwait(false);
1011 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
1012 }
1013
1014 /// <summary>
1015 /// Submits a collection of required tool call outputs to a run and resumes the run.
1016 /// </summary>
1017 /// <param name="threadId"> The thread ID of the thread being run. </param>
1018 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
1019 /// <param name="toolOutputs">
1020 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
1021 /// </param>
1022 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1023 /// <returns> The <see cref="ThreadRun"/>, updated after the submission was processed. </returns>
1024 public virtual ClientResult<ThreadRun> SubmitToolOutputsToRun(
1025 string threadId,
1026 string runId,
1027 IEnumerable<ToolOutput> toolOutputs,
1028 CancellationToken cancellationToken = default)
1029 {
1030 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1031 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1032
1033 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs).ToBinaryContent();
1034 ClientResult protocolResult = SubmitToolOutputsToRun(threadId, runId, content, cancellationToken.ToRequestOptions());
1035 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
1036 }
1037
1038 /// <summary>
1039 /// Submits a collection of required tool call outputs to a run and resumes the run with streaming enabled.
1040 /// </summary>
1041 /// <param name="threadId"> The thread ID of the thread being run. </param>
1042 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
1043 /// <param name="toolOutputs">
1044 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
1045 /// </param>
1046 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1047 public virtual AsyncCollectionResult<StreamingUpdate> SubmitToolOutputsToRunStreamingAsync(
1048 string threadId,
1049 string runId,
1050 IEnumerable<ToolOutput> toolOutputs,
1051 CancellationToken cancellationToken = default)
1052 {
1053 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1054 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1055
1056 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs.ToList(), stream: true, null)
1057 .ToBinaryContent();
1058
1059 async Task<ClientResult> sendRequestAsync() =>
1060 await SubmitToolOutputsToRunAsync(threadId, runId, content, cancellationToken.ToRequestOptions(streaming: true))
1061 .ConfigureAwait(false);
1062
1063 return new AsyncStreamingUpdateCollection(sendRequestAsync, cancellationToken);
1064 }
1065
1066 /// <summary>
1067 /// Submits a collection of required tool call outputs to a run and resumes the run with streaming enabled.
1068 /// </summary>
1069 /// <param name="threadId"> The thread ID of the thread being run. </param>
1070 /// <param name="runId"> The ID of the run that reached a <c>requires_action</c> status. </param>
1071 /// <param name="toolOutputs">
1072 /// The tool outputs, corresponding to <see cref="InternalRequiredToolCall"/> instances from the run.
1073 /// </param>
1074 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1075 public virtual CollectionResult<StreamingUpdate> SubmitToolOutputsToRunStreaming(
1076 string threadId,
1077 string runId,
1078 IEnumerable<ToolOutput> toolOutputs,
1079 CancellationToken cancellationToken = default)
1080 {
1081 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1082 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1083
1084 BinaryContent content = new InternalSubmitToolOutputsRunRequest(toolOutputs.ToList(), stream: true, null)
1085 .ToBinaryContent();
1086
1087 ClientResult sendRequest() => SubmitToolOutputsToRun(threadId, runId, content, cancellationToken.ToRequestOptions(streaming: true));
1088 return new StreamingUpdateCollection(sendRequest, cancellationToken);
1089 }
1090
1091 /// <summary>
1092 /// Cancels an in-progress <see cref="ThreadRun"/>.
1093 /// </summary>
1094 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1095 /// <param name="runId"> The ID of the run to cancel. </param>
1096 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1097 /// <returns> An updated <see cref="ThreadRun"/> instance, reflecting the new status of the run. </returns>
1098 public virtual async Task<ClientResult<ThreadRun>> CancelRunAsync(string threadId, string runId, CancellationToken cancellationToken = default)
1099 {
1100 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1101 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1102
1103 ClientResult protocolResult = await CancelRunAsync(threadId, runId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
1104 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
1105 }
1106
1107 /// <summary>
1108 /// Cancels an in-progress <see cref="ThreadRun"/>.
1109 /// </summary>
1110 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1111 /// <param name="runId"> The ID of the run to cancel. </param>
1112 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1113 /// <returns> An updated <see cref="ThreadRun"/> instance, reflecting the new status of the run. </returns>
1114 public virtual ClientResult<ThreadRun> CancelRun(string threadId, string runId, CancellationToken cancellationToken = default)
1115 {
1116 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1117 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1118
1119 ClientResult protocolResult = CancelRun(threadId, runId, cancellationToken.ToRequestOptions());
1120 return CreateResultFromProtocol(protocolResult, ThreadRun.FromResponse);
1121 }
1122
1123 /// <summary>
1124 /// Gets a page collection holding <see cref="RunStep"/> instances associated with a <see cref="ThreadRun"/>.
1125 /// </summary>
1126 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1127 /// <param name="runId"> The ID of the run to list run steps from. </param>
1128 /// <param name="options"></param>
1129 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1130 /// <returns> A collection of <see cref="RunStep"/>. </returns>
1131 public virtual AsyncCollectionResult<RunStep> GetRunStepsAsync(
1132 string threadId,
1133 string runId,
1134 RunStepCollectionOptions options = default,
1135 CancellationToken cancellationToken = default)
1136 {
1137 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1138 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1139
1140 return GetRunStepsAsync(threadId, runId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions())
1141 as AsyncCollectionResult<RunStep>;
1142 }
1143
1144 /// <summary>
1145 /// Rehydrates a page collection holding <see cref="RunStep"/> instances from a page token.
1146 /// </summary>
1147 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
1148 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1149 /// <returns> A collection of <see cref="RunStep"/>. </returns>
1150 public virtual AsyncCollectionResult<RunStep> GetRunStepsAsync(
1151 ContinuationToken firstPageToken,
1152 CancellationToken cancellationToken = default)
1153 {
1154 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
1155
1156 RunStepCollectionPageToken pageToken = RunStepCollectionPageToken.FromToken(firstPageToken);
1157 AsyncCollectionResult result = GetRunStepsAsync(pageToken?.ThreadId, pageToken?.RunId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
1158
1159 if (result is not AsyncCollectionResult<RunStep> collection)
1160 {
1161 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'AsyncCollectionResult<RunStep>'.");
1162 }
1163
1164 return collection;
1165 }
1166
1167 /// <summary>
1168 /// Gets a page collection holding <see cref="RunStep"/> instances associated with a <see cref="ThreadRun"/>.
1169 /// </summary>
1170 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1171 /// <param name="runId"> The ID of the run to list run steps from. </param>
1172 /// <param name="options"></param>
1173 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1174 /// <returns> A collection of <see cref="RunStep"/>. </returns>
1175 public virtual CollectionResult<RunStep> GetRunSteps(
1176 string threadId,
1177 string runId,
1178 RunStepCollectionOptions options = default,
1179 CancellationToken cancellationToken = default)
1180 {
1181 Argument.AssertNotNullOrEmpty(threadId, nameof(threadId));
1182 Argument.AssertNotNullOrEmpty(runId, nameof(runId));
1183
1184 CollectionResult result = GetRunSteps(threadId, runId, options?.PageSizeLimit, options?.Order?.ToString(), options?.AfterId, options?.BeforeId, cancellationToken.ToRequestOptions());
1185
1186 if (result is not CollectionResult<RunStep> collection)
1187 {
1188 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<RunStep>'.");
1189 }
1190
1191 return collection;
1192 }
1193
1194 /// <summary>
1195 /// Rehydrates a page collection holding <see cref="RunStep"/> instances from a page token.
1196 /// </summary>
1197 /// <param name="firstPageToken"> Page token corresponding to the first page of the collection to rehydrate. </param>
1198 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1199 /// <returns> A collection of <see cref="RunStep"/>. </returns>
1200 public virtual CollectionResult<RunStep> GetRunSteps(
1201 ContinuationToken firstPageToken,
1202 CancellationToken cancellationToken = default)
1203 {
1204 Argument.AssertNotNull(firstPageToken, nameof(firstPageToken));
1205
1206 RunStepCollectionPageToken pageToken = RunStepCollectionPageToken.FromToken(firstPageToken);
1207 CollectionResult result = GetRunSteps(pageToken?.ThreadId, pageToken?.RunId, pageToken?.Limit, pageToken?.Order, pageToken?.After, pageToken?.Before, cancellationToken.ToRequestOptions());
1208
1209 if (result is not CollectionResult<RunStep> collection)
1210 {
1211 throw new InvalidOperationException("Failed to cast protocol return type to expected collection type 'CollectionResult<RunStep>'.");
1212 }
1213
1214 return collection;
1215 }
1216
1217 /// <summary>
1218 /// Gets a single run step from a run.
1219 /// </summary>
1220 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1221 /// <param name="runId"> The ID of the run. </param>
1222 /// <param name="stepId"> The ID of the run step. </param>
1223 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1224 /// <returns> A <see cref="RunStep"/> instance corresponding to the specified step. </returns>
1225 public virtual async Task<ClientResult<RunStep>> GetRunStepAsync(string threadId, string runId, string stepId, CancellationToken cancellationToken = default)
1226 {
1227 ClientResult protocolResult = await GetRunStepAsync(threadId, runId, stepId, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
1228 return CreateResultFromProtocol(protocolResult, RunStep.FromResponse);
1229 }
1230
1231 /// <summary>
1232 /// Gets a single run step from a run.
1233 /// </summary>
1234 /// <param name="threadId"> The ID of the thread associated with the run. </param>
1235 /// <param name="runId"> The ID of the run. </param>
1236 /// <param name="stepId"> The ID of the run step. </param>
1237 /// <param name="cancellationToken">A token that can be used to cancel this method call.</param>
1238 /// <returns> A <see cref="RunStep"/> instance corresponding to the specified step. </returns>
1239 public virtual ClientResult<RunStep> GetRunStep(string threadId, string runId, string stepId, CancellationToken cancellationToken = default)
1240 {
1241 ClientResult protocolResult = GetRunStep(threadId, runId, stepId, cancellationToken.ToRequestOptions());
1242 return CreateResultFromProtocol(protocolResult, RunStep.FromResponse);
1243 }
1244
1245 private static BinaryContent CreateThreadAndRunProtocolContent(
1246 string assistantId,
1247 ThreadCreationOptions threadOptions,
1248 RunCreationOptions runOptions)
1249 {
1250 Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId));
1251 InternalCreateThreadAndRunRequest internalRequest = new(
1252 assistantId,
1253 threadOptions,
1254 runOptions.ModelOverride,
1255 runOptions.InstructionsOverride,
1256 runOptions.ToolsOverride,
1257 // TODO: reconcile exposure of the the two different tool_resources, if needed
1258 threadOptions?.ToolResources,
1259 runOptions.Metadata,
1260 runOptions.Temperature,
1261 runOptions.NucleusSamplingFactor,
1262 runOptions.Stream,
1263 runOptions.MaxInputTokenCount,
1264 runOptions.MaxOutputTokenCount,
1265 runOptions.TruncationStrategy,
1266 runOptions.ToolConstraint,
1267 runOptions.AllowParallelToolCalls,
1268 runOptions.ResponseFormat,
1269 serializedAdditionalRawData: null);
1270 return internalRequest.ToBinaryContent();
1271 }
1272
1273 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1274 private static ClientResult<T> CreateResultFromProtocol<T>(ClientResult protocolResult, Func<PipelineResponse, T> responseDeserializer)
1275 {
1276 PipelineResponse pipelineResponse = protocolResult?.GetRawResponse();
1277 T deserializedResultValue = responseDeserializer.Invoke(pipelineResponse);
1278 return ClientResult.FromValue(deserializedResultValue, pipelineResponse);
1279 }
1280}