openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.2.0-beta.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/Custom/Assistants/AssistantClient.cs

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