1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Common utilities for the xAI SDK.
//!
//! Provides shared functionality and utilities used across the xAI SDK,
//! including channel creation, authentication interceptors, and common types.
pub mod channel {
use crate::XAI_API_URL;
use crate::export::transport::{Channel, ClientTlsConfig, Error};
/// Creates a TLS-enabled gRPC `Channel` to the xAI API endpoint.
///
/// Configures Tonic with native root certificates and connects to
/// the SDK's default endpoint defined by [`XAI_API_URL`].
///
/// # Returns
/// * `Result<Channel, Error>` - Connected channel or transport error
///
pub async fn new() -> Result<Channel, Error> {
Channel::from_static(XAI_API_URL)
.tls_config(ClientTlsConfig::new().with_native_roots())?
.connect()
.await
}
}
pub mod interceptor {
use crate::export::metadata::MetadataValue;
use crate::export::service::Interceptor;
use crate::export::{Request, Status};
/// Concrete interceptor type for client contexts.
///
/// Erases the concrete interceptor implementation, allowing use as a concrete type
/// in return positions and stored in structs where `impl Interceptor` cannot be used.
///
/// `Send + Sync`, making it safe to use across thread boundaries.
pub struct ClientInterceptor {
inner: Box<dyn Interceptor + Send + Sync>,
}
impl ClientInterceptor {
/// Creates a new `ClientInterceptor` from any interceptor.
///
/// The interceptor is boxed internally, allowing use as a concrete type
/// in contexts where `impl Interceptor` cannot be used.
///
/// # Arguments
/// * `inner` - Any `Send + Sync` type implementing `Interceptor`
///
pub fn new(inner: impl Interceptor + Send + Sync + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
}
impl From<Box<dyn Interceptor + Send + Sync>> for ClientInterceptor {
fn from(inner: Box<dyn Interceptor + Send + Sync>) -> Self {
Self { inner }
}
}
impl Interceptor for ClientInterceptor {
fn call(&mut self, request: tonic::Request<()>) -> Result<tonic::Request<()>, Status> {
self.inner.call(request)
}
}
/// Creates an interceptor that injects a Bearer token `authorization` header.
///
/// Header value is set to `Bearer {api_key}`. This is the default
/// authentication mechanism used by SDK client constructors.
///
/// # Arguments
/// * `api_key` - Valid xAI API key for Bearer authentication
///
/// # Returns
/// * `ClientInterceptor` - Interceptor that adds authorization metadata
///
pub fn auth(api_key: &str) -> ClientInterceptor {
let api_key = api_key.to_string();
ClientInterceptor::new(move |mut req: Request<()>| -> Result<Request<()>, Status> {
let token = MetadataValue::try_from(&format!("Bearer {}", api_key)).map_err(|e| {
Status::invalid_argument(format!("Failed to create metadata value: {}", e))
})?;
req.metadata_mut().insert("authorization", token);
Ok(req)
})
}
/// Composes multiple interceptors into a single interceptor, applied in order.
///
/// Each interceptor receives the output request of the previous one. If any interceptor
/// returns an error, the composed interceptor returns that error immediately.
///
/// # Arguments
/// * `interceptors` - Vector of boxed interceptor functions applied sequentially
///
/// # Returns
/// * `ClientInterceptor` - Single interceptor that applies all provided interceptors
///
pub fn compose(mut interceptors: Vec<Box<dyn Interceptor + Send + Sync>>) -> ClientInterceptor {
ClientInterceptor::new(move |mut req: Request<()>| -> Result<Request<()>, Status> {
for int in interceptors.iter_mut() {
req = int.call(req)?;
}
Ok(req)
})
}
}
pub mod types {
use std::error::Error;
use std::pin::Pin;
/// Type-erased error that is `Send + Sync`, for use in types sent across threads or
/// with generic sink callbacks that require `Sync` futures.
pub type BoxError = Box<dyn Error + Send + Sync>;
/// Boxed future type for async callbacks. Allows references without `Send` requirement.
pub type BoxFuture<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
}