1use crate::{
2 config::Config,
3 error::OpenAIError,
4 types::realtime::{
5 RealtimeCallAcceptRequest, RealtimeCallCreateRequest, RealtimeCallCreateResponse,
6 RealtimeCallReferRequest, RealtimeCallRejectRequest, RealtimeCreateClientSecretRequest,
7 RealtimeCreateClientSecretResponse,
8 },
9 Client, RequestOptions,
10};
11
12pub struct Realtime<'c, C: Config> {
15 client: &'c Client<C>,
16 pub(crate) request_options: RequestOptions,
17}
18
19impl<'c, C: Config> Realtime<'c, C> {
20 pub fn new(client: &'c Client<C>) -> Self {
21 Self {
22 client,
23 request_options: RequestOptions::new(),
24 }
25 }
26
27 pub async fn create_call(
32 &self,
33 request: RealtimeCallCreateRequest,
34 ) -> Result<RealtimeCallCreateResponse, OpenAIError> {
35 let (bytes, headers) = self
36 .client
37 .post_form_raw("/realtime/calls", request, &self.request_options)
38 .await?;
39
40 let location = headers
42 .get("location")
43 .and_then(|v| v.to_str().ok())
44 .map(|s| s.to_string());
45
46 if location.is_none() {
47 tracing::warn!("Location header not found in Realtime call creation response");
48 }
49
50 let sdp = String::from_utf8_lossy(&bytes).into_owned();
52
53 Ok(RealtimeCallCreateResponse { sdp, location })
54 }
55
56 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
59 pub async fn accept_call(
60 &self,
61 call_id: &str,
62 request: RealtimeCallAcceptRequest,
63 ) -> Result<(), OpenAIError> {
64 self.client
65 .post(
66 &format!("/realtime/calls/{}/accept", call_id),
67 request,
68 &self.request_options,
69 )
70 .await
71 }
72
73 #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
75 pub async fn hangup_call(&self, call_id: &str) -> Result<(), OpenAIError> {
76 self.client
77 .post(
78 &format!("/realtime/calls/{}/hangup", call_id),
79 (),
80 &self.request_options,
81 )
82 .await
83 }
84
85 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
87 pub async fn refer_call(
88 &self,
89 call_id: &str,
90 request: RealtimeCallReferRequest,
91 ) -> Result<(), OpenAIError> {
92 self.client
93 .post(
94 &format!("/realtime/calls/{}/refer", call_id),
95 request,
96 &self.request_options,
97 )
98 .await
99 }
100
101 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
103 pub async fn reject_call(
104 &self,
105 call_id: &str,
106 request: RealtimeCallRejectRequest,
107 ) -> Result<(), OpenAIError> {
108 self.client
109 .post(
110 &format!("/realtime/calls/{}/reject", call_id),
111 request,
112 &self.request_options,
113 )
114 .await
115 }
116
117 #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
119 pub async fn create_client_secret(
120 &self,
121 request: RealtimeCreateClientSecretRequest,
122 ) -> Result<RealtimeCreateClientSecretResponse, OpenAIError> {
123 self.client
124 .post("/realtime/client_secrets", request, &self.request_options)
125 .await
126 }
127}