use tonic::codegen::InterceptedService;
use tonic::metadata::{Ascii, MetadataValue};
use tonic::service::Interceptor;
use tonic::transport::{Channel, Endpoint};
use tonic::{Request, Status};
use crate::proto::admin_service_client::AdminServiceClient;
use crate::proto::graph_rag_service_client::GraphRagServiceClient;
use crate::proto::knowledge_graph_service_client::KnowledgeGraphServiceClient;
use crate::proto::knowledge_service_client::KnowledgeServiceClient;
use crate::proto::memory_service_client::MemoryServiceClient;
use crate::proto::tools_service_client::ToolsServiceClient;
#[derive(Clone)]
pub struct AuthInterceptor {
token: Option<MetadataValue<Ascii>>,
}
impl Interceptor for AuthInterceptor {
fn call(&mut self, mut request: Request<()>) -> Result<Request<()>, Status> {
if let Some(token) = &self.token {
request
.metadata_mut()
.insert("authorization", token.clone());
}
Ok(request)
}
}
type Svc = InterceptedService<Channel, AuthInterceptor>;
#[derive(Clone)]
pub struct CortexClient {
channel: Channel,
interceptor: AuthInterceptor,
}
pub struct CortexClientBuilder {
endpoint: String,
token: Option<String>,
}
impl CortexClientBuilder {
pub fn token(mut self, token: impl Into<String>) -> Self {
self.token = Some(token.into());
self
}
pub async fn connect(self) -> Result<CortexClient, Box<dyn std::error::Error + Send + Sync>> {
let channel = Endpoint::from_shared(self.endpoint)?.connect().await?;
let token = match self.token {
Some(t) => Some(format!("Bearer {t}").parse()?),
None => None,
};
Ok(CortexClient {
channel,
interceptor: AuthInterceptor { token },
})
}
}
impl CortexClient {
pub async fn connect(
endpoint: impl Into<String>,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
Self::builder(endpoint).connect().await
}
pub fn builder(endpoint: impl Into<String>) -> CortexClientBuilder {
CortexClientBuilder {
endpoint: endpoint.into(),
token: None,
}
}
fn svc(&self) -> Svc {
InterceptedService::new(self.channel.clone(), self.interceptor.clone())
}
pub fn admin(&self) -> AdminServiceClient<Svc> {
AdminServiceClient::new(self.svc())
}
pub fn knowledge(&self) -> KnowledgeServiceClient<Svc> {
KnowledgeServiceClient::new(self.svc())
}
pub fn memory(&self) -> MemoryServiceClient<Svc> {
MemoryServiceClient::new(self.svc())
}
pub fn graph(&self) -> KnowledgeGraphServiceClient<Svc> {
KnowledgeGraphServiceClient::new(self.svc())
}
pub fn graphrag(&self) -> GraphRagServiceClient<Svc> {
GraphRagServiceClient::new(self.svc())
}
pub fn tools(&self) -> ToolsServiceClient<Svc> {
ToolsServiceClient::new(self.svc())
}
}