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
14pub 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 pub fn steps(&self, run_id: &str) -> Steps<C> {
32 Steps::new(self.client, &self.thread_id, run_id)
33 }
34
35 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}