async_openai/
runs.rs

1use serde::Serialize;
2
3use crate::{
4    config::Config,
5    error::OpenAIError,
6    steps::Steps,
7    types::{
8        AssistantEventStream, CreateRunRequest, ListRunsResponse, ModifyRunRequest, RunObject,
9        SubmitToolOutputsRunRequest,
10    },
11    Client,
12};
13
14/// Represents an execution run on a thread.
15///
16/// Related guide: [Assistants](https://platform.openai.com/docs/assistants/overview)
17pub struct Runs<'c, C: Config> {
18    pub thread_id: String,
19    client: &'c Client<C>,
20}
21
22impl<'c, C: Config> Runs<'c, C> {
23    pub fn new(client: &'c Client<C>, thread_id: &str) -> Self {
24        Self {
25            client,
26            thread_id: thread_id.into(),
27        }
28    }
29
30    ///  [Steps] API group
31    pub fn steps(&self, run_id: &str) -> Steps<C> {
32        Steps::new(self.client, &self.thread_id, run_id)
33    }
34
35    /// Create a run.
36    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
37    pub async fn create(&self, request: CreateRunRequest) -> Result<RunObject, OpenAIError> {
38        self.client
39            .post(&format!("/threads/{}/runs", self.thread_id), request)
40            .await
41    }
42
43    /// Create a run.
44    ///
45    /// byot: You must ensure "stream: true" in serialized `request`
46    #[crate::byot(
47        T0 = serde::Serialize,
48        R = serde::de::DeserializeOwned,
49        stream = "true",
50        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
51    )]
52    #[allow(unused_mut)]
53    pub async fn create_stream(
54        &self,
55        mut request: CreateRunRequest,
56    ) -> Result<AssistantEventStream, OpenAIError> {
57        #[cfg(not(feature = "byot"))]
58        {
59            if request.stream.is_some() && !request.stream.unwrap() {
60                return Err(OpenAIError::InvalidArgument(
61                    "When stream is false, use Runs::create".into(),
62                ));
63            }
64
65            request.stream = Some(true);
66        }
67
68        Ok(self
69            .client
70            .post_stream_mapped_raw_events(
71                &format!("/threads/{}/runs", self.thread_id),
72                request,
73                TryFrom::try_from,
74            )
75            .await)
76    }
77
78    /// Retrieves a run.
79    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
80    pub async fn retrieve(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
81        self.client
82            .get(&format!("/threads/{}/runs/{run_id}", self.thread_id))
83            .await
84    }
85
86    /// Modifies a run.
87    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
88    pub async fn update(
89        &self,
90        run_id: &str,
91        request: ModifyRunRequest,
92    ) -> Result<RunObject, OpenAIError> {
93        self.client
94            .post(
95                &format!("/threads/{}/runs/{run_id}", self.thread_id),
96                request,
97            )
98            .await
99    }
100
101    /// Returns a list of runs belonging to a thread.
102    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
103    pub async fn list<Q>(&self, query: &Q) -> Result<ListRunsResponse, OpenAIError>
104    where
105        Q: Serialize + ?Sized,
106    {
107        self.client
108            .get_with_query(&format!("/threads/{}/runs", self.thread_id), &query)
109            .await
110    }
111
112    /// When a run has the status: "requires_action" and required_action.type is submit_tool_outputs, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request.
113    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
114    pub async fn submit_tool_outputs(
115        &self,
116        run_id: &str,
117        request: SubmitToolOutputsRunRequest,
118    ) -> Result<RunObject, OpenAIError> {
119        self.client
120            .post(
121                &format!(
122                    "/threads/{}/runs/{run_id}/submit_tool_outputs",
123                    self.thread_id
124                ),
125                request,
126            )
127            .await
128    }
129
130    /// byot: You must ensure "stream: true" in serialized `request`
131    #[crate::byot(
132        T0 = std::fmt::Display,
133        T1 = serde::Serialize,
134        R = serde::de::DeserializeOwned,
135        stream = "true",
136        where_clause = "R: std::marker::Send + 'static + TryFrom<eventsource_stream::Event, Error = OpenAIError>"
137    )]
138    #[allow(unused_mut)]
139    pub async fn submit_tool_outputs_stream(
140        &self,
141        run_id: &str,
142        mut request: SubmitToolOutputsRunRequest,
143    ) -> Result<AssistantEventStream, OpenAIError> {
144        #[cfg(not(feature = "byot"))]
145        {
146            if request.stream.is_some() && !request.stream.unwrap() {
147                return Err(OpenAIError::InvalidArgument(
148                    "When stream is false, use Runs::submit_tool_outputs".into(),
149                ));
150            }
151
152            request.stream = Some(true);
153        }
154
155        Ok(self
156            .client
157            .post_stream_mapped_raw_events(
158                &format!(
159                    "/threads/{}/runs/{run_id}/submit_tool_outputs",
160                    self.thread_id
161                ),
162                request,
163                TryFrom::try_from,
164            )
165            .await)
166    }
167
168    /// Cancels a run that is `in_progress`
169    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
170    pub async fn cancel(&self, run_id: &str) -> Result<RunObject, OpenAIError> {
171        self.client
172            .post(
173                &format!("/threads/{}/runs/{run_id}/cancel", self.thread_id),
174                (),
175            )
176            .await
177    }
178}