Skip to main content

ares/api/handlers/
user_agents.rs

1use crate::{
2    db::postgres::UserAgent,
3    db::traits::DatabaseClient,
4    types::{AppError, Result},
5    AppState,
6};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Deserialize)]
11pub struct CreateUserAgentReq {
12    pub name: String,
13    pub display_name: Option<String>,
14    pub description: Option<String>,
15    pub model: String,
16    pub system_prompt: Option<String>,
17    pub tools: Vec<String>,
18    #[serde(default = "default_max_iterations")]
19    pub max_tool_iterations: i32,
20    #[serde(default)]
21    pub parallel_tools: bool,
22    #[serde(default)]
23    pub is_public: bool,
24    #[serde(default)]
25    pub extra: HashMap<String, serde_json::Value>,
26}
27
28fn default_max_iterations() -> i32 {
29    10
30}
31
32#[derive(Debug, Serialize)]
33pub struct UserAgentResponse {
34    pub id: String,
35    pub name: String,
36    pub display_name: Option<String>,
37    pub description: Option<String>,
38    pub model: String,
39    pub system_prompt: Option<String>,
40    pub tools: Vec<String>,
41    pub max_tool_iterations: i32,
42    pub parallel_tools: bool,
43    pub is_public: bool,
44    pub usage_count: i32,
45    pub average_rating: Option<f32>,
46    pub created_at: i64,
47    pub updated_at: i64,
48}
49
50impl From<UserAgent> for UserAgentResponse {
51    fn from(agent: UserAgent) -> Self {
52        let tools = agent.tools_vec();
53        let rating = agent.average_rating();
54        Self {
55            id: agent.id,
56            name: agent.name,
57            display_name: agent.display_name,
58            description: agent.description,
59            model: agent.model,
60            system_prompt: agent.system_prompt,
61            tools,
62            max_tool_iterations: agent.max_tool_iterations,
63            parallel_tools: agent.parallel_tools,
64            is_public: agent.is_public,
65            usage_count: agent.usage_count,
66            average_rating: rating,
67            created_at: agent.created_at,
68            updated_at: agent.updated_at,
69        }
70    }
71}
72
73pub async fn resolve_agent(
74    state: &AppState,
75    user_id: &str,
76    agent_name: String,
77) -> Result<(UserAgent, String)> {
78    if let Some(agent) = state
79        .db
80        .get_user_agent_by_name(user_id, &agent_name)
81        .await?
82    {
83        return Ok((agent, "user".to_string()));
84    }
85
86    if let Some(agent) = state.db.get_public_agent_by_name(&agent_name).await? {
87        return Ok((agent, "community".to_string()));
88    }
89
90    // Tier 3: fall back to system agents from TOON/TOML config
91    let config = state.config_manager.config();
92    if let Some(agent_cfg) = config.get_agent(&agent_name) {
93        let now = chrono::Utc::now().timestamp();
94        let system_agent = crate::db::postgres::UserAgent {
95            id: format!("system-{}", agent_name),
96            user_id: "system".to_string(),
97            name: agent_name.clone(),
98            display_name: None,
99            description: None,
100            model: agent_cfg.model.clone(),
101            system_prompt: agent_cfg.system_prompt.clone(),
102            tools: serde_json::to_string(&agent_cfg.tools).unwrap_or_else(|_| "[]".to_string()),
103            max_tool_iterations: agent_cfg.max_tool_iterations as i32,
104            parallel_tools: agent_cfg.parallel_tools,
105            extra: "{}".to_string(),
106            is_public: true,
107            usage_count: 0,
108            rating_sum: 0,
109            rating_count: 0,
110            created_at: now,
111            updated_at: now,
112        };
113        return Ok((system_agent, "system".to_string()));
114    }
115
116    Err(AppError::NotFound(format!("Agent '{}' not found", agent_name)))
117}
118
119// Dummy stubs to fix routing
120pub async fn list_agents() {}
121pub async fn create_agent() {}
122pub async fn import_agent_toon() {}
123pub async fn get_agent() {}
124pub async fn update_agent() {}
125pub async fn delete_agent() {}
126pub async fn export_agent_toon() {}