pub mod agents;
pub mod built_in;
pub mod config;
pub mod context;
pub mod invocation;
pub mod manager;
pub mod mcp_tools;
pub mod orchestrator;
pub mod parser;
pub mod registry;
pub mod worktree;
pub use agents::AgentRegistry;
pub use agents::AgentResult;
pub use agents::AgentStatus;
pub use agents::CodeReviewerAgent;
pub use agents::DebuggerAgent;
pub use agents::DocsAgent;
pub use agents::Finding;
pub use agents::PerformanceAgent;
pub use agents::RefactorerAgent;
pub use agents::SecurityAgent;
pub use agents::Severity;
pub use agents::Subagent;
pub use agents::TestWriterAgent;
pub use built_in::create_default_registry;
pub use built_in::register_built_in_agents;
pub use config::IntelligenceLevel;
pub use config::SubagentConfig;
pub use config::ToolPermission;
pub use context::AgentContext;
pub use context::AgentContextSnapshot;
pub use context::AgentMessage;
pub use context::CancellationToken;
pub use context::ContextError;
pub use context::ContextFinding;
pub use context::ContextResult;
pub use context::ExecutionMetricsSnapshot;
pub use context::FindingSeverity;
pub use context::MessagePriority;
pub use context::MessageReceiver;
pub use context::MessageTarget;
pub use context::MessageType;
pub use context::ProgressEvent;
pub use context::ProgressInfo;
pub use context::ProgressStage;
pub use context::ProgressTracker;
pub use invocation::AgentChain;
pub use invocation::AgentInvocation;
pub use invocation::ExecutionPlan;
pub use invocation::ExecutionStep;
pub use invocation::InvocationParser;
pub use invocation::InvocationRequest;
pub use manager::AgentHandle;
pub use manager::AgentManager;
pub use manager::AgentStats;
pub use manager::MessageBus;
pub use mcp_tools::McpAgentHandler;
pub use mcp_tools::McpAgentTool;
pub use mcp_tools::McpAgentToolProvider;
pub use orchestrator::AgentOrchestrator;
pub use orchestrator::ContextSnapshot;
pub use orchestrator::OrchestratorConfig;
pub use orchestrator::OrchestratorResult;
pub use orchestrator::ProgressUpdate;
pub use orchestrator::SharedContext;
pub use parser::AgentParser;
pub use parser::ChainOperator;
pub use parser::ParsedInvocation;
pub use registry::SubagentRegistry;
pub use registry::SubagentRegistryError;
pub use worktree::AgentWorktree;
pub use worktree::ConflictStrategy;
pub use worktree::MergeResult;
pub use worktree::WorktreeManager;
pub use worktree::WorktreePool;
use crate::modes::OperatingMode;
use std::collections::HashMap;
use uuid::Uuid;
pub type SubagentResult<T> = std::result::Result<T, SubagentError>;
#[derive(thiserror::Error, Debug)]
pub enum SubagentError {
#[error("agent not found: {name}")]
AgentNotFound { name: String },
#[error("invalid agent configuration: {0}")]
InvalidConfig(String),
#[error("agent execution failed: {0}")]
ExecutionFailed(String),
#[error("circular dependency detected in agent chain: {chain:?}")]
CircularDependency { chain: Vec<String> },
#[error("agent timeout: {name}")]
Timeout { name: String },
#[error("tool permission denied: {tool} for agent {agent}")]
ToolPermissionDenied { tool: String, agent: String },
#[error("mode restriction violation: {mode:?} does not allow {operation}")]
ModeRestriction {
mode: OperatingMode,
operation: String,
},
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("serialization error: {0}")]
Serialization(#[from] toml::de::Error),
#[error("tool error: {0}")]
Tool(#[from] crate::code_tools::ToolError),
#[error("file watching error: {0}")]
FileWatcher(String),
#[error("agent template not found: {name}")]
TemplateNotFound { name: String },
}
#[derive(Debug, Clone)]
pub struct SubagentContext {
pub execution_id: Uuid,
pub mode: OperatingMode,
pub available_tools: Vec<String>,
pub conversation_context: String,
pub working_directory: std::path::PathBuf,
pub parameters: HashMap<String, String>,
pub metadata: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SubagentStatus {
Pending,
Running,
Completed,
Failed(String),
Cancelled,
}
#[derive(Debug, Clone)]
pub struct SubagentExecution {
pub id: Uuid,
pub agent_name: String,
pub status: SubagentStatus,
pub output: Option<String>,
pub modified_files: Vec<std::path::PathBuf>,
pub started_at: std::time::SystemTime,
pub completed_at: Option<std::time::SystemTime>,
pub error: Option<String>,
}
impl SubagentExecution {
pub fn new(agent_name: String) -> Self {
Self {
id: Uuid::new_v4(),
agent_name,
status: SubagentStatus::Pending,
output: None,
modified_files: Vec::new(),
started_at: std::time::SystemTime::now(),
completed_at: None,
error: None,
}
}
pub fn start(&mut self) {
self.status = SubagentStatus::Running;
self.started_at = std::time::SystemTime::now();
}
pub fn complete(&mut self, output: String, modified_files: Vec<std::path::PathBuf>) {
self.status = SubagentStatus::Completed;
self.output = Some(output);
self.modified_files = modified_files;
self.completed_at = Some(std::time::SystemTime::now());
}
pub fn fail(&mut self, error: String) {
self.status = SubagentStatus::Failed(error.clone());
self.error = Some(error);
self.completed_at = Some(std::time::SystemTime::now());
}
pub fn duration(&self) -> Option<std::time::Duration> {
self.completed_at
.and_then(|end| end.duration_since(self.started_at).ok())
}
}
#[cfg(test)]
mod basic_tests {
use super::*;
#[test]
fn test_subagent_execution_lifecycle() {
let mut execution = SubagentExecution::new("test-agent".to_string());
assert_eq!(execution.status, SubagentStatus::Pending);
assert_eq!(execution.agent_name, "test-agent");
execution.start();
assert_eq!(execution.status, SubagentStatus::Running);
execution.complete("Success!".to_string(), vec![]);
assert_eq!(execution.status, SubagentStatus::Completed);
assert_eq!(execution.output.as_ref().unwrap(), "Success!");
assert!(execution.duration().is_some());
}
#[test]
fn test_subagent_execution_failure() {
let mut execution = SubagentExecution::new("failing-agent".to_string());
execution.start();
execution.fail("Something went wrong".to_string());
assert!(matches!(execution.status, SubagentStatus::Failed(_)));
assert_eq!(execution.error.as_ref().unwrap(), "Something went wrong");
assert!(execution.duration().is_some());
}
}
#[cfg(test)]
mod tests;