mod builtin;
mod index;
#[cfg(feature = "cli-integration")]
mod index_loader;
pub use builtin::{
bash_subagent, builtin_subagents, explore_subagent, find_builtin, general_purpose_subagent,
plan_subagent,
};
pub use index::SubagentIndex;
#[cfg(feature = "cli-integration")]
pub use index_loader::{SubagentFrontmatter, SubagentIndexLoader};
#[cfg(test)]
mod tests {
use super::*;
use crate::client::ModelConfig;
use crate::common::{ContentSource, SourceType, ToolRestricted};
#[test]
fn test_subagent_index() {
let subagent = SubagentIndex::new("reviewer", "Code reviewer")
.source(ContentSource::in_memory("Review the code"))
.source_type(SourceType::Project)
.tools(["Read", "Grep", "Glob"])
.model("haiku");
assert_eq!(subagent.name, "reviewer");
assert!(subagent.has_tool_restrictions());
assert!(subagent.is_tool_allowed("Read"));
assert!(!subagent.is_tool_allowed("Bash"));
let config = ModelConfig::default();
assert!(subagent.resolve_model(&config).contains("haiku"));
}
#[test]
fn test_tool_pattern_matching() {
let subagent = SubagentIndex::new("git-agent", "Git helper")
.source(ContentSource::in_memory("Help with git"))
.tools(["Bash(git:*)", "Read"]);
assert!(subagent.is_tool_allowed("Bash"));
assert!(subagent.is_tool_allowed("Read"));
assert!(!subagent.is_tool_allowed("Write"));
}
#[test]
fn test_no_tool_restrictions() {
let subagent = SubagentIndex::new("general-purpose", "General purpose agent")
.source(ContentSource::in_memory("Do anything"));
assert!(!subagent.has_tool_restrictions());
assert!(subagent.is_tool_allowed("Anything"));
}
#[test]
fn test_resolve_model_with_alias() {
let config = ModelConfig::default();
let subagent = SubagentIndex::new("fast", "Fast agent")
.source(ContentSource::in_memory("Be quick"))
.model("haiku");
assert!(subagent.resolve_model(&config).contains("haiku"));
let subagent = SubagentIndex::new("smart", "Smart agent")
.source(ContentSource::in_memory("Think deep"))
.model("opus");
assert!(subagent.resolve_model(&config).contains("opus"));
let subagent = SubagentIndex::new("balanced", "Balanced agent")
.source(ContentSource::in_memory("Be balanced"))
.model("sonnet");
assert!(subagent.resolve_model(&config).contains("sonnet"));
let subagent = SubagentIndex::new("custom", "Custom agent")
.source(ContentSource::in_memory("Custom"))
.model("claude-custom-model-v1");
assert_eq!(subagent.resolve_model(&config), "claude-custom-model-v1");
}
#[test]
fn test_resolve_model_with_type() {
use crate::client::ModelType;
let config = ModelConfig::default();
let subagent = SubagentIndex::new("typed", "Typed agent")
.source(ContentSource::in_memory("Use type"))
.model_type(ModelType::Small);
assert!(subagent.resolve_model(&config).contains("haiku"));
}
}