use crate::protocol::{EndpointConfig, ProtocolError, ServiceConfig};
use crate::{Error, Result};
use std::collections::HashMap;
use std::future::Future;
use super::core::AiClient;
pub trait EndpointExt {
fn resolve_endpoint(&self, name: &str) -> Result<&EndpointConfig>;
fn call_service(
&self,
service_name: &str,
) -> impl Future<Output = Result<serde_json::Value>> + Send;
fn list_remote_models(&self) -> impl Future<Output = Result<Vec<String>>> + Send;
}
impl EndpointExt for AiClient {
fn resolve_endpoint(&self, name: &str) -> Result<&EndpointConfig> {
self.manifest
.endpoints
.as_ref()
.and_then(|eps: &HashMap<String, EndpointConfig>| eps.get(name))
.ok_or_else(|| {
Error::Protocol(ProtocolError::NotFound {
id: name.to_string(),
hint: None,
})
})
}
async fn call_service(&self, service_name: &str) -> Result<serde_json::Value> {
let service = self
.manifest
.services
.as_ref()
.and_then(|services: &HashMap<String, ServiceConfig>| services.get(service_name))
.ok_or_else(|| {
Error::Protocol(ProtocolError::NotFound {
id: service_name.to_string(),
hint: None,
})
})?;
self.transport
.execute_service(
&service.path,
&service.method,
service.headers.as_ref(),
service.query_params.as_ref(),
)
.await
}
async fn list_remote_models(&self) -> Result<Vec<String>> {
let response = self.call_service("list_models").await?;
let models: Vec<String> = if let Some(data) = response.get("data") {
data.as_array()
.unwrap_or(&vec![])
.iter()
.filter_map(|m| {
m.get("id")
.and_then(|id| id.as_str().map(|s| s.to_string()))
})
.collect()
} else if let Some(models) = response.get("models") {
models
.as_array()
.unwrap_or(&vec![])
.iter()
.filter_map(|m| {
m.get("name")
.and_then(|n| n.as_str().map(|s| s.to_string()))
})
.collect()
} else {
vec![]
};
Ok(models)
}
}