zai_rs/realtime/client.rs
1//! [`RealtimeClient`] — entry point for the realtime API.
2
3use std::sync::Arc;
4
5use super::session::SessionBuilder;
6use crate::client::endpoints::{ApiBase, EndpointConfig};
7
8/// Authentication mode for the realtime WebSocket handshake.
9#[derive(Debug, Clone)]
10pub enum AuthMode {
11 /// Server-side Bearer auth: `Authorization: Bearer {API_KEY}` (default).
12 Bearer,
13 /// Client-side JWT auth: a short-lived token signed from the API key's
14 /// secret, so the secret never leaves the server. Used when the WebSocket
15 /// is opened directly from a browser/device.
16 Jwt {
17 /// Token validity in seconds.
18 ttl_seconds: i64,
19 },
20}
21
22/// Entry point for the realtime API.
23///
24/// Construct with [`RealtimeClient::new`], optionally switch to JWT auth via
25/// [`RealtimeClient::with_jwt`], then start a session with
26/// [`RealtimeClient::session`].
27///
28/// ```rust,no_run
29/// use zai_rs::{model::GLM4_voice, realtime::RealtimeClient};
30///
31/// # async fn go(key: String) -> zai_rs::ZaiResult<()> {
32/// let session = RealtimeClient::new(key)
33/// .session(GLM4_voice {})
34/// .build()
35/// .await?;
36/// # Ok(())
37/// # }
38/// ```
39#[derive(Clone)]
40pub struct RealtimeClient {
41 api_key: Arc<String>,
42 auth: AuthMode,
43 endpoint_config: EndpointConfig,
44}
45
46impl RealtimeClient {
47 /// Create a realtime client using Bearer auth and the default endpoints.
48 pub fn new(api_key: impl Into<String>) -> Self {
49 Self {
50 api_key: Arc::new(api_key.into()),
51 auth: AuthMode::Bearer,
52 endpoint_config: EndpointConfig::default(),
53 }
54 }
55
56 /// Switch to client-side JWT auth, signing tokens valid for `ttl_seconds`.
57 pub fn with_jwt(mut self, ttl_seconds: i64) -> Self {
58 self.auth = AuthMode::Jwt { ttl_seconds };
59 self
60 }
61
62 /// Switch (back) to server-side Bearer auth.
63 pub fn with_bearer(mut self) -> Self {
64 self.auth = AuthMode::Bearer;
65 self
66 }
67
68 /// Override the full endpoint config (base URLs).
69 pub fn with_endpoint_config(mut self, config: EndpointConfig) -> Self {
70 self.endpoint_config = config;
71 self
72 }
73
74 /// Override only the realtime base URL (`wss://...`).
75 pub fn with_realtime_base(mut self, base: impl Into<String>) -> Self {
76 self.endpoint_config = self.endpoint_config.with_realtime_base(base);
77 self
78 }
79
80 /// Begin building a realtime session for `model`.
81 ///
82 /// The model bound is checked at compile time via [`super::RealtimeModel`].
83 pub fn session<M: super::RealtimeModel>(&self, model: M) -> SessionBuilder {
84 let realtime_url = self.realtime_url();
85 let model_name: String = model.into();
86 SessionBuilder::new(
87 Arc::clone(&self.api_key),
88 self.auth.clone(),
89 realtime_url,
90 model_name,
91 )
92 }
93
94 /// The resolved realtime WebSocket URL.
95 pub fn realtime_url(&self) -> String {
96 self.endpoint_config.url(&ApiBase::Realtime, "")
97 }
98
99 /// Current auth mode.
100 pub fn auth(&self) -> &AuthMode {
101 &self.auth
102 }
103
104 /// A reference to the configured API key.
105 pub fn api_key(&self) -> &str {
106 &self.api_key
107 }
108}