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