//! Agent 配置模板 HTTP 处理器 use axum::{ extract::{Extension, Path, Query, State}, Json, }; use crate::state::AppState; use crate::error::SaasResult; use crate::auth::types::AuthContext; use crate::auth::handlers::{log_operation, check_permission}; use super::types::*; use super::service; /// GET /api/v1/agent-templates — 列出 Agent 模板 pub async fn list_templates( State(state): State, Extension(ctx): Extension, Query(query): Query, ) -> SaasResult>> { check_permission(&ctx, "model:read")?; Ok(Json(service::list_templates(&state.db, &query).await?)) } /// POST /api/v1/agent-templates — 创建 Agent 模板 pub async fn create_template( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "model:manage")?; let category = req.category.as_deref().unwrap_or("general"); let source = req.source.as_deref().unwrap_or("custom"); let visibility = req.visibility.as_deref().unwrap_or("public"); let tools = req.tools.as_deref().unwrap_or(&[]); let capabilities = req.capabilities.as_deref().unwrap_or(&[]); let scenarios = req.scenarios.as_deref().unwrap_or(&[]); let quick_commands = req.quick_commands.as_deref().unwrap_or(&[]); let result = service::create_template( &state.db, &req.name, req.description.as_deref(), category, source, req.model.as_deref(), req.system_prompt.as_deref(), tools, capabilities, req.temperature, req.max_tokens, visibility, req.soul_content.as_deref(), Some(scenarios), req.welcome_message.as_deref(), Some(quick_commands), req.personality.as_deref(), req.communication_style.as_deref(), req.emoji.as_deref(), req.source_id.as_deref(), ).await?; log_operation(&state.db, &ctx.account_id, "agent_template.create", "agent_template", &result.id, Some(serde_json::json!({"name": req.name})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// GET /api/v1/agent-templates/:id — 获取单个 Agent 模板 pub async fn get_template( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> SaasResult> { check_permission(&ctx, "model:read")?; Ok(Json(service::get_template(&state.db, &id).await?)) } /// GET /api/v1/agent-templates/:id/full — 获取完整 Agent 模板(含扩展字段) pub async fn get_full_template( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> SaasResult> { check_permission(&ctx, "model:read")?; // Reuses the same get_template service which already returns all fields Ok(Json(service::get_template(&state.db, &id).await?)) } /// GET /api/v1/agent-templates/available — 列出公开可用模板(轻量级) pub async fn list_available( State(state): State, Extension(ctx): Extension, ) -> SaasResult>> { check_permission(&ctx, "model:read")?; Ok(Json(service::list_available(&state.db).await?)) } /// POST /api/v1/agent-templates/:id — 更新 Agent 模板 pub async fn update_template( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "model:manage")?; let result = service::update_template( &state.db, &id, req.description.as_deref(), req.model.as_deref(), req.system_prompt.as_deref(), req.tools.as_deref(), req.capabilities.as_deref(), req.temperature, req.max_tokens, req.visibility.as_deref(), req.status.as_deref(), req.soul_content.as_deref(), req.scenarios.as_deref(), req.welcome_message.as_deref(), req.quick_commands.as_deref(), req.personality.as_deref(), req.communication_style.as_deref(), req.emoji.as_deref(), ).await?; log_operation(&state.db, &ctx.account_id, "agent_template.update", "agent_template", &id, None, ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// DELETE /api/v1/agent-templates/:id — 归档 Agent 模板 pub async fn archive_template( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> SaasResult> { check_permission(&ctx, "model:manage")?; let result = service::archive_template(&state.db, &id).await?; log_operation(&state.db, &ctx.account_id, "agent_template.archive", "agent_template", &id, None, ctx.client_ip.as_deref()).await?; Ok(Json(result)) } // --- Template Assignment --- /// POST /api/v1/accounts/me/assign-template — 分配行业模板到当前账户 pub async fn assign_template( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "relay:use")?; let result = service::assign_template_to_account( &state.db, &ctx.account_id, &req.template_id, ).await?; log_operation(&state.db, &ctx.account_id, "account.assign_template", "agent_template", &req.template_id, None, ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// GET /api/v1/accounts/me/assigned-template — 获取已分配的行业模板 pub async fn get_assigned_template( State(state): State, Extension(ctx): Extension, ) -> SaasResult>> { check_permission(&ctx, "model:read")?; Ok(Json(service::get_assigned_template(&state.db, &ctx.account_id).await?)) } /// DELETE /api/v1/accounts/me/assigned-template — 取消行业模板分配 pub async fn unassign_template( State(state): State, Extension(ctx): Extension, ) -> SaasResult> { check_permission(&ctx, "relay:use")?; service::unassign_template(&state.db, &ctx.account_id).await?; Ok(Json(serde_json::json!({"ok": true}))) } /// POST /api/v1/agent-templates/:id/create-agent — 从模板创建 Agent 配置 pub async fn create_agent_from_template( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> SaasResult> { check_permission(&ctx, "model:read")?; Ok(Json(service::create_agent_from_template(&state.db, &id).await?)) }