async_openai_compat/
threads.rs

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