openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.0.0-beta.12

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/Custom/Assistants/AssistantClient.cs

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