async_openai/assistants/
threads.rs

1use crate::{
2    config::Config,
3    error::OpenAIError,
4    types::assistants::{
5        CreateThreadAndRunRequest, CreateThreadRequest, DeleteThreadResponse, ModifyThreadRequest,
6        RunObject, ThreadObject,
7    },
8    Client, Messages, RequestOptions, Runs,
9};
10
11#[cfg(not(target_family = "wasm"))]
12use crate::types::assistants::AssistantEventStream;
13
14/// Create threads that assistants can interact with.
15///
16/// Related guide: [Assistants](https://platform.openai.com/docs/assistants/overview)
17pub struct Threads<'c, C: Config> {
18    client: &'c Client<C>,
19    pub(crate) request_options: RequestOptions,
20}
21
22impl<'c, C: Config> Threads<'c, C> {
23    pub fn new(client: &'c Client<C>) -> Self {
24        Self {
25            client,
26            request_options: RequestOptions::new(),
27        }
28    }
29
30    /// Call [Messages] group API to manage message in `thread_id` thread.
31    pub fn messages(&self, thread_id: &str) -> Messages<'_, C> {
32        Messages::new(self.client, thread_id)
33    }
34
35    /// Call [Runs] group API to manage runs in `thread_id` thread.
36    pub fn runs(&self, thread_id: &str) -> Runs<'_, C> {
37        Runs::new(self.client, thread_id)
38    }
39
40    /// Create a thread and run it in one request.
41    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
42    pub async fn create_and_run(
43        &self,
44        request: CreateThreadAndRunRequest,
45    ) -> Result<RunObject, OpenAIError> {
46        self.client
47            .post("/threads/runs", request, &self.request_options)
48            .await
49    }
50
51    /// Create a thread and run it in one request (streaming).
52    ///
53    /// byot: You must ensure "stream: true" in serialized `request`
54    #[cfg(not(target_family = "wasm"))]
55    #[crate::byot(
56        T0 = serde::Serialize,
57        R = serde::de::DeserializeOwned,
58        stream = "true",
59        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
60    )]
61    #[allow(unused_mut)]
62    pub async fn create_and_run_stream(
63        &self,
64        mut request: CreateThreadAndRunRequest,
65    ) -> Result<AssistantEventStream, OpenAIError> {
66        #[cfg(not(feature = "byot"))]
67        {
68            if request.stream.is_some() && !request.stream.unwrap() {
69                return Err(OpenAIError::InvalidArgument(
70                    "When stream is false, use Threads::create_and_run".into(),
71                ));
72            }
73
74            request.stream = Some(true);
75        }
76        Ok(self
77            .client
78            .post_stream_mapped_raw_events(
79                "/threads/runs",
80                request,
81                &self.request_options,
82                TryFrom::try_from,
83            )
84            .await)
85    }
86
87    /// Create a thread.
88    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
89    pub async fn create(&self, request: CreateThreadRequest) -> Result<ThreadObject, OpenAIError> {
90        self.client
91            .post("/threads", request, &self.request_options)
92            .await
93    }
94
95    /// Retrieves a thread.
96    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
97    pub async fn retrieve(&self, thread_id: &str) -> Result<ThreadObject, OpenAIError> {
98        self.client
99            .get(&format!("/threads/{thread_id}"), &self.request_options)
100            .await
101    }
102
103    /// Modifies a thread.
104    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
105    pub async fn update(
106        &self,
107        thread_id: &str,
108        request: ModifyThreadRequest,
109    ) -> Result<ThreadObject, OpenAIError> {
110        self.client
111            .post(
112                &format!("/threads/{thread_id}"),
113                request,
114                &self.request_options,
115            )
116            .await
117    }
118
119    /// Delete a thread.
120    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
121    pub async fn delete(&self, thread_id: &str) -> Result<DeleteThreadResponse, OpenAIError> {
122        self.client
123            .delete(&format!("/threads/{thread_id}"), &self.request_options)
124            .await
125    }
126}