gitdataai/libs/agent/model/capability.rs
ZhenYi 10c0cc007b refactor(agent): split into submodules and add Qdrant embedding
- Split agent crate into client/, model/, agent/ subdirs
- Add billing.rs for token usage recording
- Add sync.rs for upstream model sync
- EmbedService: Qdrant-backed vector memory for semantic search
- ChatService: wire EmbedService for memory lookup, passive skill awareness
- ReAct loop: streamline with tokio::select! and proper error handling
2026-04-25 20:09:33 +08:00

115 lines
3.4 KiB
Rust

//! 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<bool>,
}
#[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<Utc>,
}
impl From<model_capability::Model> 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<Vec<ModelCapabilityResponse>, 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<ModelCapabilityResponse, AgentError> {
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<ModelCapabilityResponse, AgentError> {
let _ = request
.capability
.parse::<CapabilityType>()
.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<ModelCapabilityResponse, AgentError> {
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(())
}