use serde::{Deserialize, Serialize};
use typed_builder::TypedBuilder;
use super::{AgentBehavior, BuiltinTools, SystemInstructions};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TypedBuilder, Default)]
#[builder(field_defaults(default))]
pub struct SubagentCapabilities {
#[serde(default)]
pub agent_behavior: AgentBehavior,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(setter(strip_option))]
pub allowed_subagents: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(setter(strip_option))]
pub enabled_tools: Option<Vec<BuiltinTools>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(setter(strip_option))]
pub disabled_tools: Option<Vec<BuiltinTools>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TypedBuilder)]
pub struct SubagentConfig {
#[builder(setter(into))]
pub name: String,
#[builder(setter(into))]
pub description: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(default, setter(into, strip_option))]
pub system_instructions: Option<SystemInstructions>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub capabilities: Option<SubagentCapabilities>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default, setter(transform = |v: impl IntoIterator<Item = impl Into<String>>| v.into_iter().map(Into::into).collect()))]
pub tools: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_subagent_config_builder() {
let sub = SubagentConfig::builder()
.name("researcher")
.description("Performs deep web and code research")
.system_instructions("You are a specialized researcher.")
.capabilities(
SubagentCapabilities::builder()
.agent_behavior(AgentBehavior::Autonomous)
.allowed_subagents(vec!["summarizer".to_string()])
.enabled_tools(vec![BuiltinTools::SearchWeb, BuiltinTools::ReadUrlContent])
.build(),
)
.tools(vec!["custom_scraper".to_string()])
.build();
assert_eq!(sub.name, "researcher");
assert_eq!(sub.description, "Performs deep web and code research");
assert!(sub.capabilities.is_some());
let caps = sub.capabilities.unwrap();
assert_eq!(caps.agent_behavior, AgentBehavior::Autonomous);
assert_eq!(caps.allowed_subagents, Some(vec!["summarizer".to_string()]));
assert_eq!(sub.tools, vec!["custom_scraper"]);
}
#[test]
fn test_subagent_config_serde_roundtrip() {
let sub = SubagentConfig::builder()
.name("coder")
.description("Writes code")
.build();
let json = serde_json::to_string(&sub).expect("serialize");
let parsed: SubagentConfig = serde_json::from_str(&json).expect("deserialize");
assert_eq!(sub.name, parsed.name);
assert_eq!(sub.description, parsed.description);
}
}