use crate::handlers::AppState;
use crate::handlers::chat::ModelTier;
use axum::{Json, extract::State};
use serde::Serialize;
#[derive(Serialize)]
pub struct ModelsResponse {
pub models: Vec<ModelStatus>,
}
#[derive(Serialize)]
pub struct ModelStatus {
pub name: String,
pub tier: ModelTier,
pub endpoint: String,
pub healthy: bool,
pub last_check_seconds_ago: u64,
pub consecutive_failures: u32,
}
pub async fn handler(State(state): State<AppState>) -> Json<ModelsResponse> {
let health_statuses = state.selector().health_checker().get_all_statuses().await;
let config = state.config();
let models: Vec<ModelStatus> = health_statuses
.into_iter()
.map(|h| {
let tier = if config.models.fast.iter().any(|e| e.name() == h.name()) {
ModelTier::Fast
} else if config.models.balanced.iter().any(|e| e.name() == h.name()) {
ModelTier::Balanced
} else if config.models.deep.iter().any(|e| e.name() == h.name()) {
ModelTier::Deep
} else {
tracing::warn!(
endpoint_name = %h.name(),
"Endpoint not found in any tier, defaulting to Balanced"
);
ModelTier::Balanced
};
ModelStatus {
name: h.name().to_string(),
tier,
endpoint: h.base_url().to_string(),
healthy: h.is_healthy(),
last_check_seconds_ago: h.last_check().elapsed().as_secs(),
consecutive_failures: h.consecutive_failures(),
}
})
.collect();
tracing::debug!(
total_models = models.len(),
healthy_count = models.iter().filter(|m| m.healthy).count(),
"Retrieved model status for /models endpoint"
);
Json(ModelsResponse { models })
}