use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
pub struct OrchestratorConfig {
pub event_buffer_size: usize,
pub control_buffer_size: usize,
pub max_concurrent_subagents: usize,
pub subject_prefix: String,
}
impl Default for OrchestratorConfig {
fn default() -> Self {
Self {
event_buffer_size: 1000,
control_buffer_size: 100,
max_concurrent_subagents: 50,
subject_prefix: "agent".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubAgentConfig {
pub agent_type: String,
pub description: String,
pub prompt: String,
#[serde(default)]
pub permissive: bool,
#[serde(default)]
pub permissive_deny: Vec<String>,
pub max_steps: Option<usize>,
pub timeout_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
#[serde(default)]
pub metadata: serde_json::Value,
#[serde(default = "default_workspace")]
pub workspace: String,
#[serde(default)]
pub agent_dirs: Vec<String>,
#[serde(default)]
pub skill_dirs: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lane_config: Option<crate::queue::SessionQueueConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubAgentInfo {
pub id: String,
pub agent_type: String,
pub description: String,
pub state: String,
pub parent_id: Option<String>,
pub created_at: u64,
pub updated_at: u64,
pub current_activity: Option<SubAgentActivity>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum SubAgentActivity {
Idle,
CallingTool {
tool_name: String,
args: serde_json::Value,
},
RequestingLlm { message_count: usize },
WaitingForControl { reason: String },
}
impl SubAgentConfig {
pub fn new(agent_type: impl Into<String>, prompt: impl Into<String>) -> Self {
Self {
agent_type: agent_type.into(),
description: String::new(),
prompt: prompt.into(),
permissive: false,
permissive_deny: Vec::new(),
max_steps: None,
timeout_ms: None,
parent_id: None,
metadata: serde_json::Value::Null,
workspace: default_workspace(),
agent_dirs: Vec::new(),
skill_dirs: Vec::new(),
lane_config: None,
}
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
pub fn with_permissive(mut self, permissive: bool) -> Self {
self.permissive = permissive;
self
}
pub fn with_permissive_deny(mut self, deny_rules: Vec<String>) -> Self {
self.permissive_deny = deny_rules;
self
}
pub fn with_max_steps(mut self, max_steps: usize) -> Self {
self.max_steps = Some(max_steps);
self
}
pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = Some(timeout_ms);
self
}
pub fn with_parent_id(mut self, parent_id: impl Into<String>) -> Self {
self.parent_id = Some(parent_id.into());
self
}
pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = metadata;
self
}
pub fn with_workspace(mut self, workspace: impl Into<String>) -> Self {
self.workspace = workspace.into();
self
}
pub fn with_agent_dirs(mut self, dirs: Vec<String>) -> Self {
self.agent_dirs = dirs;
self
}
pub fn with_skill_dirs(mut self, dirs: Vec<String>) -> Self {
self.skill_dirs = dirs;
self
}
pub fn with_lane_config(mut self, config: crate::queue::SessionQueueConfig) -> Self {
self.lane_config = Some(config);
self
}
}
fn default_workspace() -> String {
".".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentSlot {
pub agent_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<crate::agent_teams::TeamRole>,
pub description: String,
pub prompt: String,
#[serde(default)]
pub permissive: bool,
#[serde(default)]
pub permissive_deny: Vec<String>,
pub max_steps: Option<usize>,
pub timeout_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
#[serde(default)]
pub metadata: serde_json::Value,
#[serde(default = "default_workspace")]
pub workspace: String,
#[serde(default)]
pub agent_dirs: Vec<String>,
#[serde(default)]
pub skill_dirs: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lane_config: Option<crate::queue::SessionQueueConfig>,
}
impl AgentSlot {
pub fn new(agent_type: impl Into<String>, prompt: impl Into<String>) -> Self {
Self {
agent_type: agent_type.into(),
role: None,
description: String::new(),
prompt: prompt.into(),
permissive: false,
permissive_deny: Vec::new(),
max_steps: None,
timeout_ms: None,
parent_id: None,
metadata: serde_json::Value::Null,
workspace: default_workspace(),
agent_dirs: Vec::new(),
skill_dirs: Vec::new(),
lane_config: None,
}
}
pub fn with_role(mut self, role: crate::agent_teams::TeamRole) -> Self {
self.role = Some(role);
self
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
pub fn with_permissive(mut self, permissive: bool) -> Self {
self.permissive = permissive;
self
}
pub fn with_permissive_deny(mut self, deny_rules: Vec<String>) -> Self {
self.permissive_deny = deny_rules;
self
}
pub fn with_max_steps(mut self, max_steps: usize) -> Self {
self.max_steps = Some(max_steps);
self
}
pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = Some(timeout_ms);
self
}
pub fn with_parent_id(mut self, parent_id: impl Into<String>) -> Self {
self.parent_id = Some(parent_id.into());
self
}
pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = metadata;
self
}
pub fn with_workspace(mut self, workspace: impl Into<String>) -> Self {
self.workspace = workspace.into();
self
}
pub fn with_agent_dirs(mut self, dirs: Vec<String>) -> Self {
self.agent_dirs = dirs;
self
}
pub fn with_skill_dirs(mut self, dirs: Vec<String>) -> Self {
self.skill_dirs = dirs;
self
}
pub fn with_lane_config(mut self, config: crate::queue::SessionQueueConfig) -> Self {
self.lane_config = Some(config);
self
}
}
impl From<SubAgentConfig> for AgentSlot {
fn from(c: SubAgentConfig) -> Self {
Self {
agent_type: c.agent_type,
role: None,
description: c.description,
prompt: c.prompt,
permissive: c.permissive,
permissive_deny: c.permissive_deny,
max_steps: c.max_steps,
timeout_ms: c.timeout_ms,
parent_id: c.parent_id,
metadata: c.metadata,
workspace: c.workspace,
agent_dirs: c.agent_dirs,
skill_dirs: c.skill_dirs,
lane_config: c.lane_config,
}
}
}
impl From<AgentSlot> for SubAgentConfig {
fn from(s: AgentSlot) -> Self {
Self {
agent_type: s.agent_type,
description: s.description,
prompt: s.prompt,
permissive: s.permissive,
permissive_deny: s.permissive_deny,
max_steps: s.max_steps,
timeout_ms: s.timeout_ms,
parent_id: s.parent_id,
metadata: s.metadata,
workspace: s.workspace,
agent_dirs: s.agent_dirs,
skill_dirs: s.skill_dirs,
lane_config: s.lane_config,
}
}
}