use std::sync::Arc;
use ::cordis::Context;
use super::*;
use ares_llm::provider_registry::{ModelInfo, RuntimeProviderEntry};
use ares_types::types::{AppError};
use crate::Result;
use crate::HttpError;
use axum::{
Json,
extract::{Path, Query, State},
http::StatusCode,
};
use sha2::Digest;
pub async fn list_models_handler(State(ctx): State<Arc<Context>>) -> Result<Json<Vec<ModelInfo>>> {
Ok(Json(ctx.get::<ares_llm::Llm>().expect("not provided").list_models()))
}
pub async fn reload_runtime_provider_registry(ctx: &Arc<Context>) -> Result<()> {
let __pool_1 = ctx.get::<ares_store::TenantDb>().expect("not provided").pool().clone();
let store = RuntimeProviderStore::new(&__pool_1);
let providers = store.list_all().await?;
let mut entries = Vec::with_capacity(providers.len());
let mut names = Vec::with_capacity(providers.len());
for provider in providers {
let (headers, api_key) = runtime_provider_entry_headers_and_key(provider.headers.as_ref());
names.push(provider.name);
entries.push(RuntimeProviderEntry {
tenant_id: provider.tenant_id,
display_name: provider.display_name,
provider_type: provider.provider_type,
api_base: provider.api_base,
auth_type: provider.auth_type,
default_model: provider.default_model,
headers,
api_key,
enabled: provider.enabled,
});
}
let Some(llm) = ctx.get::<ares_llm::Llm>() else {
tracing::info!(
"Runtime providers preload skipped: no Llm service on this context"
);
return Ok(());
};
llm.reload_runtime_providers(entries, names);
Ok(())
}
pub async fn list_runtime_providers(
State(ctx): State<Arc<Context>>,
) -> Result<Json<Vec<RuntimeProviderResponse>>> {
let __pool_2 = ctx.get::<ares_store::TenantDb>().expect("not provided").pool().clone();
let store = RuntimeProviderStore::new(&__pool_2);
let providers = store.list_all().await?;
let response: Vec<RuntimeProviderResponse> = providers.into_iter().map(|p| p.into()).collect();
tracing::info!("Listed {} runtime providers", response.len());
Ok(Json(response))
}
pub async fn get_runtime_provider(
State(ctx): State<Arc<Context>>,
Path(name): Path<String>,
Query(query): Query<RuntimeProviderScopeQuery>,
) -> Result<Json<RuntimeProviderResponse>> {
let __pool_3 = ctx.get::<ares_store::TenantDb>().expect("not provided").pool().clone();
let store = RuntimeProviderStore::new(&__pool_3);
let provider = store
.get_scoped(query.tenant_id.as_deref(), &name)
.await?
.ok_or_else(|| HttpError::from(AppError::NotFound(format!("runtime provider {name} not found"))))?;
tracing::info!("Retrieved runtime provider {}", name);
Ok(Json(provider.into()))
}
pub async fn upsert_runtime_provider(
State(ctx): State<Arc<Context>>,
Json(mut req): Json<CreateRuntimeProviderRequest>,
) -> Result<Json<RuntimeProviderResponse>> {
let __pool_4 = ctx.get::<ares_store::TenantDb>().expect("not provided").pool().clone();
let store = RuntimeProviderStore::new(&__pool_4);
preserve_redacted_runtime_provider_secret(&store, &mut req).await?;
let provider = store.upsert(&req).await?;
reload_runtime_provider_registry(&ctx).await?;
tracing::info!("Upserted runtime provider {}", provider.name);
Ok(Json(provider.into()))
}
pub async fn delete_runtime_provider(
State(ctx): State<Arc<Context>>,
Path(name): Path<String>,
Query(query): Query<RuntimeProviderScopeQuery>,
) -> Result<StatusCode> {
let __pool_5 = ctx.get::<ares_store::TenantDb>().expect("not provided").pool().clone();
let store = RuntimeProviderStore::new(&__pool_5);
let rows = store
.delete_scoped(query.tenant_id.as_deref(), &name)
.await?;
if rows == 0 {
return Err(HttpError::from(AppError::NotFound(format!(
"runtime provider {name} not found"
).into())));
}
reload_runtime_provider_registry(&ctx).await?;
tracing::info!("Deleted runtime provider {}", name);
Ok(StatusCode::NO_CONTENT)
}
pub fn routes() -> axum::Router<Arc<Context>> {
use axum::routing::{delete, get, post};
axum::Router::new()
.route("/providers/list_models_handler", get(list_models_handler))
.route("/providers/list_runtime_providers", get(list_runtime_providers))
.route("/providers/get_runtime_provider", get(get_runtime_provider))
.route("/providers/upsert_runtime_provider", post(upsert_runtime_provider))
.route("/providers/delete_runtime_provider", delete(delete_runtime_provider))
}
use ::cordis::Service;