//! Model capability management — CRUD. use chrono::Utc; use db::database::AppDatabase; use models::agents::CapabilityType; use models::agents::model_capability; use sea_orm::*; use crate::error::AgentError; #[derive(Debug, Clone, serde::Deserialize, utoipa::ToSchema)] pub struct CreateModelCapabilityRequest { pub model_version_id: i64, pub capability: String, #[serde(default)] pub is_supported: bool, } #[derive(Debug, Clone, serde::Deserialize, utoipa::ToSchema)] pub struct UpdateModelCapabilityRequest { pub is_supported: Option, } #[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)] pub struct ModelCapabilityResponse { pub id: i64, pub model_version_id: i64, pub capability: String, pub is_supported: bool, pub created_at: chrono::DateTime, } impl From for ModelCapabilityResponse { fn from(mc: model_capability::Model) -> Self { Self { id: mc.id, model_version_id: mc.model_version_id, capability: mc.capability, is_supported: mc.is_supported, created_at: mc.created_at, } } } pub async fn list_capabilities( db: &AppDatabase, model_version_id: i64, ) -> Result, AgentError> { let caps = model_capability::Entity::find() .filter(model_capability::Column::ModelVersionId.eq(model_version_id)) .order_by_asc(model_capability::Column::Capability) .all(db) .await?; Ok(caps.into_iter().map(ModelCapabilityResponse::from).collect()) } pub async fn get_capability( db: &AppDatabase, id: i64, ) -> Result { let cap = model_capability::Entity::find_by_id(id) .one(db) .await? .ok_or_else(|| AgentError::NotFound(format!("Capability record not found: {}", id)))?; Ok(ModelCapabilityResponse::from(cap)) } pub async fn create_capability( db: &AppDatabase, request: CreateModelCapabilityRequest, ) -> Result { let _ = request .capability .parse::() .map_err(|_| AgentError::InvalidInput { field: "capability".into(), reason: "Invalid capability type".into(), })?; let now = Utc::now(); let active = model_capability::ActiveModel { model_version_id: Set(request.model_version_id), capability: Set(request.capability), is_supported: Set(request.is_supported), created_at: Set(now), ..Default::default() }; let cap = active.insert(db).await?; Ok(ModelCapabilityResponse::from(cap)) } pub async fn update_capability( db: &AppDatabase, id: i64, request: UpdateModelCapabilityRequest, ) -> Result { let cap = model_capability::Entity::find_by_id(id) .one(db) .await? .ok_or_else(|| AgentError::NotFound(format!("Capability record not found: {}", id)))?; let mut active: model_capability::ActiveModel = cap.into(); if let Some(is_supported) = request.is_supported { active.is_supported = Set(is_supported); } let cap = active.update(db).await?; Ok(ModelCapabilityResponse::from(cap)) } pub async fn delete_capability(db: &AppDatabase, id: i64) -> Result<(), AgentError> { model_capability::Entity::delete_by_id(id).exec(db).await?; Ok(()) }