use crate::common::ApiState;
use crate::common::{ApiError, ApiResult, Json, State};
use serde_json::{json, Value};
use std::collections::HashMap;
#[utoipa::path(
get,
path = "/v1/output/targets",
tag = "outputs",
responses(
(status = 200, description = "Output targets", body = HashMap<String, serde_json::Value>),
(status = 500, description = "Internal server error")
)
)]
pub async fn get_targets(State(state): State<ApiState>) -> ApiResult<Json<HashMap<String, Value>>> {
let agent_service = state
.agent_service
.as_ref()
.ok_or_else(|| ApiError::internal("Agent service not available"))?;
let agent_ids = agent_service
.list_agents()
.await
.map_err(|e| ApiError::internal(format!("Failed to list agents: {}", e)))?;
let mut motor_agents = Vec::new();
for agent_id in agent_ids {
if let Ok(props) = agent_service.get_agent_properties(&agent_id).await {
if props.capabilities.contains_key("motor")
|| props.capabilities.contains_key("output")
|| props.agent_type.to_lowercase().contains("motor")
{
motor_agents.push(agent_id);
}
}
}
let mut response = HashMap::new();
response.insert("targets".to_string(), json!(motor_agents));
Ok(Json(response))
}
#[utoipa::path(
post,
path = "/v1/output/configure",
tag = "outputs",
responses(
(status = 200, description = "Outputs configured", body = HashMap<String, String>),
(status = 500, description = "Internal server error")
)
)]
pub async fn post_configure(
State(_state): State<ApiState>,
Json(request): Json<HashMap<String, Value>>,
) -> ApiResult<Json<HashMap<String, String>>> {
let config = request
.get("config")
.ok_or_else(|| ApiError::invalid_input("Missing 'config' field"))?;
if !config.is_object() {
return Err(ApiError::invalid_input("'config' must be an object"));
}
tracing::info!(target: "feagi-api", "Output configuration updated: {} targets",
config.as_object().map(|o| o.len()).unwrap_or(0));
Ok(Json(HashMap::from([(
"message".to_string(),
"Outputs configured successfully".to_string(),
)])))
}