//! Model version management — CRUD. //! //! All functions take `&DatabaseConnection` instead of `&AppService`. use chrono::Utc; use db::database::AppDatabase; use models::agents::model_version; use models::agents::{ ModelStatus, model_version::{Column as MVColumn, Entity as MVEntity, Model as ModelVersionModel}, }; use sea_orm::*; use uuid::Uuid; use crate::error::AgentError; #[derive(Debug, Clone, serde::Deserialize, utoipa::ToSchema)] pub struct CreateModelVersionRequest { pub model_id: Uuid, pub version: String, pub release_date: Option>, pub change_log: Option, #[serde(default)] pub is_default: bool, } #[derive(Debug, Clone, serde::Deserialize, utoipa::ToSchema)] pub struct UpdateModelVersionRequest { pub version: Option, pub release_date: Option>, pub change_log: Option, pub is_default: Option, pub status: Option, } #[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)] pub struct ModelVersionResponse { pub id: Uuid, pub model_id: Uuid, pub version: String, pub release_date: Option>, pub change_log: Option, pub is_default: bool, pub status: String, pub created_at: chrono::DateTime, } impl From for ModelVersionResponse { fn from(mv: ModelVersionModel) -> Self { Self { id: mv.id, model_id: mv.model_id, version: mv.version, release_date: mv.release_date, change_log: mv.change_log, is_default: mv.is_default, status: mv.status, created_at: mv.created_at, } } } /// List model versions, optionally filtered by model. pub async fn list_versions( db: &AppDatabase, model_id: Option, ) -> Result, AgentError> { let mut query = MVEntity::find().order_by_asc(MVColumn::Version); if let Some(mid) = model_id { query = query.filter(MVColumn::ModelId.eq(mid)); } let versions = query.all(db).await?; Ok(versions .into_iter() .map(ModelVersionResponse::from) .collect()) } /// Get a single version by ID. pub async fn get_version(db: &AppDatabase, id: Uuid) -> Result { let version = MVEntity::find_by_id(id) .one(db) .await? .ok_or_else(|| AgentError::NotFound(format!("Model version not found: {}", id)))?; Ok(ModelVersionResponse::from(version)) } /// Create a new model version. pub async fn create_version( db: &AppDatabase, request: CreateModelVersionRequest, ) -> Result { let now = Utc::now(); let active = model_version::ActiveModel { id: Set(Uuid::now_v7()), model_id: Set(request.model_id), version: Set(request.version), release_date: Set(request.release_date), change_log: Set(request.change_log), is_default: Set(request.is_default), status: Set(ModelStatus::Active.to_string()), created_at: Set(now), ..Default::default() }; let version = active.insert(db).await?; Ok(ModelVersionResponse::from(version)) } /// Update an existing model version. pub async fn update_version( db: &AppDatabase, id: Uuid, request: UpdateModelVersionRequest, ) -> Result { let version = MVEntity::find_by_id(id) .one(db) .await? .ok_or_else(|| AgentError::NotFound(format!("Model version not found: {}", id)))?; let mut active: model_version::ActiveModel = version.into(); if let Some(v) = request.version { active.version = Set(v); } if let Some(v) = request.release_date { active.release_date = Set(Some(v)); } if let Some(v) = request.change_log { active.change_log = Set(Some(v)); } if let Some(v) = request.is_default { active.is_default = Set(v); } if let Some(v) = request.status { active.status = Set(v); } let version = active.update(db).await?; Ok(ModelVersionResponse::from(version)) } /// Delete a model version by ID. pub async fn delete_version(db: &AppDatabase, id: Uuid) -> Result<(), AgentError> { MVEntity::delete_by_id(id).exec(db).await?; Ok(()) }