Function bodies 848 total
spawn_auto_start_agents function · rust · L160-L197 (38 LOC)src/agent/manager.rs
pub fn spawn_auto_start_agents(
&mut self,
pty_size: PtySize,
) -> Vec<(String, color_eyre::eyre::Report)> {
let mut errors = Vec::new();
let projects: Vec<_> = self.config.project.clone();
for project in &projects {
for agent_config in &project.agent {
if agent_config.auto_start {
let command = agent_config
.command
.clone()
.unwrap_or_else(|| self.config.global.claude_binary.clone());
let cwd = agent_config
.cwd
.clone()
.unwrap_or_else(|| project.path.clone());
if let Err(e) = self.spawn(
agent_config.name.clone(),
project.name.clone(),
command,
agent_config.args.clone(),
cwd,
kill function · rust · L202-L211 (10 LOC)src/agent/manager.rs
pub fn kill(&mut self, id: AgentId) -> Result<()> {
match self.agents.get_mut(&id) {
Some(handle) => {
info!("Killing agent '{}'", handle.name());
handle.kill();
Ok(())
}
None => bail!("Agent {} not found", id),
}
}restart function · rust · L215-L240 (26 LOC)src/agent/manager.rs
pub fn restart(&mut self, id: AgentId, pty_size: PtySize) -> Result<AgentId> {
let params: RestartParams = match self.agents.get(&id) {
Some(handle) => handle.restart_params(),
None => bail!("Agent {} not found", id),
};
// Kill the old agent
self.kill(id)?;
// Remove old agent from collections
self.agents.remove(&id);
self.remove_from_display_order(id);
// Spawn replacement
let new_id = self.spawn(
params.name,
params.project_name,
params.command,
params.args,
params.cwd,
params.env,
pty_size,
)?;
Ok(new_id)
}retry_without_resume function · rust · L247-L293 (47 LOC)src/agent/manager.rs
pub fn retry_without_resume(&mut self, id: AgentId, pty_size: PtySize) -> Result<AgentId> {
let params = match self.agents.get(&id) {
Some(handle) => handle.restart_params(),
None => bail!("Agent {} not found", id),
};
// Strip --resume/-r and its value from args
let mut new_args: Vec<String> = Vec::new();
let mut skip_next = false;
for arg in ¶ms.args {
if skip_next {
skip_next = false;
continue;
}
if arg == "--resume" || arg == "-r" {
skip_next = true;
continue;
}
new_args.push(arg.clone());
}
// Remove the errored agent (already exited, no need to kill)
self.agents.remove(&id);
self.remove_from_display_order(id);
// Spawn fresh replacement
let new_id = self.spawn(
params.name,
params.project_name,
rename function · rust · L299-L330 (32 LOC)src/agent/manager.rs
pub fn rename(&mut self, id: AgentId, new_name: String) -> Result<String> {
// Validate non-empty
if new_name.is_empty() {
bail!("Agent name cannot be empty");
}
// Check the agent exists and get its project
let project_name = match self.agents.get(&id) {
Some(handle) => handle.project_name().to_string(),
None => bail!("Agent {} not found", id),
};
// Check for duplicate name within the same project (excluding self)
let duplicate = self
.agents
.values()
.any(|a| a.id() != id && a.project_name() == project_name && a.name() == new_name);
if duplicate {
bail!(
"Agent '{}' already exists in project '{}'",
new_name,
project_name
);
}
let handle = self.agents.get_mut(&id).unwrap();
let old_name = handle.name().to_string();
handle.set_name(nrename_project function · rust · L337-L375 (39 LOC)src/agent/manager.rs
pub fn rename_project(&mut self, old_name: &str, new_name: &str) -> Result<()> {
if new_name.is_empty() {
bail!("Project name cannot be empty");
}
if old_name == new_name {
return Ok(());
}
// Check that the old project exists
let project_exists = self.display_order.iter().any(|(name, _)| name == old_name);
if !project_exists {
bail!("Project '{}' not found", old_name);
}
// Check that the new name doesn't conflict
let name_taken = self.display_order.iter().any(|(name, _)| name == new_name);
if name_taken {
bail!("Project '{}' already exists", new_name);
}
// Update display order
for (name, _) in &mut self.display_order {
if name == old_name {
*name = new_name.to_string();
break;
}
}
// Update all agent handles that belong to this project
fokill_all function · rust · L379-L385 (7 LOC)src/agent/manager.rs
pub fn kill_all(&mut self) {
for handle in self.agents.values_mut() {
if handle.state().is_alive() {
handle.kill();
}
}
}Want this analysis on your repo? https://repobility.com/scan/
shutdown_all function · rust · L389-L418 (30 LOC)src/agent/manager.rs
pub async fn shutdown_all(&mut self, timeout: std::time::Duration) {
self.kill_all();
let deadline = tokio::time::Instant::now() + timeout;
loop {
let any_alive = self.agents.values().any(|a| a.state().is_alive());
if !any_alive {
info!("All agents have exited");
return;
}
if tokio::time::Instant::now() >= deadline {
warn!("Shutdown timeout reached -- some agents may still be running");
return;
}
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
// Re-check process status
let idle_timeout = self.config.global.idle_timeout_secs;
let ids: Vec<AgentId> = self.agents.keys().copied().collect();
for id in ids {
if let Some(handle) = self.agents.get_mut(&id) {
handle.detect_and_update(&self.detection_patterns, idle_timeout);
get function · rust · L423-L425 (3 LOC)src/agent/manager.rs
pub fn get(&self, id: AgentId) -> Option<&AgentHandle> {
self.agents.get(&id)
}get_mut function · rust · L428-L430 (3 LOC)src/agent/manager.rs
pub fn get_mut(&mut self, id: AgentId) -> Option<&mut AgentHandle> {
self.agents.get_mut(&id)
}find_by_name function · rust · L433-L438 (6 LOC)src/agent/manager.rs
pub fn find_by_name(&self, project_name: &str, agent_name: &str) -> Option<AgentId> {
self.agents
.values()
.find(|a| a.project_name() == project_name && a.name() == agent_name)
.map(|a| a.id())
}agents_by_project function · rust · L441-L443 (3 LOC)src/agent/manager.rs
pub fn agents_by_project(&self) -> &[(String, Vec<AgentId>)] {
&self.display_order
}state_counts function · rust · L446-L459 (14 LOC)src/agent/manager.rs
pub fn state_counts(&self) -> StateCounts {
let mut counts = StateCounts::default();
for handle in self.agents.values() {
match handle.state() {
AgentState::Spawning { .. } => counts.spawning += 1,
AgentState::Running { .. } => counts.running += 1,
AgentState::WaitingForInput { .. } => counts.waiting += 1,
AgentState::Idle { .. } => counts.idle += 1,
AgentState::Completed { .. } => counts.completed += 1,
AgentState::Errored { .. } => counts.errored += 1,
}
}
counts
}agent_count function · rust · L462-L464 (3 LOC)src/agent/manager.rs
pub fn agent_count(&self) -> usize {
self.agents.len()
}all_agent_ids_ordered function · rust · L467-L472 (6 LOC)src/agent/manager.rs
pub fn all_agent_ids_ordered(&self) -> Vec<AgentId> {
self.display_order
.iter()
.flat_map(|(_, ids)| ids.iter().copied())
.collect()
}Repobility — same analyzer, your code, free for public repos · /scan/
detect_all_states function · rust · L478-L495 (18 LOC)src/agent/manager.rs
pub fn detect_all_states(&mut self) -> Vec<(AgentId, AgentState, AgentState)> {
let mut changes = Vec::new();
let idle_timeout = self.config.global.idle_timeout_secs;
let agent_ids: Vec<AgentId> = self.agents.keys().copied().collect();
for id in agent_ids {
if let Some(handle) = self.agents.get_mut(&id) {
let old_state = handle.state().clone();
if let Some(new_state) =
handle.detect_and_update(&self.detection_patterns, idle_timeout)
{
changes.push((id, old_state, new_state));
}
}
}
changes
}add_empty_project function · rust · L502-L512 (11 LOC)src/agent/manager.rs
pub fn add_empty_project(&mut self, project_name: &str) -> Result<()> {
if self
.display_order
.iter()
.any(|(name, _)| name == project_name)
{
bail!("Project '{}' already exists", project_name);
}
self.display_order.push((project_name.to_string(), vec![]));
Ok(())
}remove_project function · rust · L517-L531 (15 LOC)src/agent/manager.rs
pub fn remove_project(&mut self, project_name: &str) -> Result<()> {
if let Some(pos) = self
.display_order
.iter()
.position(|(name, _)| name == project_name)
{
if !self.display_order[pos].1.is_empty() {
bail!("Project '{}' still has agents", project_name);
}
self.display_order.remove(pos);
Ok(())
} else {
bail!("Project '{}' not found", project_name);
}
}remove function · rust · L538-L541 (4 LOC)src/agent/manager.rs
pub fn remove(&mut self, id: AgentId) {
self.agents.remove(&id);
self.remove_from_display_order(id);
}add_to_display_order function · rust · L544-L556 (13 LOC)src/agent/manager.rs
fn add_to_display_order(&mut self, project_name: &str, id: AgentId) {
if let Some((_, ids)) = self
.display_order
.iter_mut()
.find(|(name, _)| name == project_name)
{
ids.push(id);
} else {
self.display_order
.push((project_name.to_string(), vec![id]));
}
}remove_from_display_order function · rust · L557-L562 (6 LOC)src/agent/manager.rs
fn remove_from_display_order(&mut self, id: AgentId) {
for (_, ids) in &mut self.display_order {
ids.retain(|&i| i != id);
}
}move_agent_up function · rust · L565-L574 (10 LOC)src/agent/manager.rs
pub fn move_agent_up(&mut self, id: AgentId) {
for (_, ids) in &mut self.display_order {
if let Some(pos) = ids.iter().position(|&i| i == id) {
if pos > 0 {
ids.swap(pos - 1, pos);
}
return;
}
}
}move_agent_down function · rust · L577-L586 (10 LOC)src/agent/manager.rs
pub fn move_agent_down(&mut self, id: AgentId) {
for (_, ids) in &mut self.display_order {
if let Some(pos) = ids.iter().position(|&i| i == id) {
if pos + 1 < ids.len() {
ids.swap(pos, pos + 1);
}
return;
}
}
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
format_status_bar function · rust · L602-L623 (22 LOC)src/agent/manager.rs
pub fn format_status_bar(&self) -> String {
let mut parts = Vec::new();
if self.running > 0 {
parts.push(format!("● {} running", self.running));
}
if self.waiting > 0 {
parts.push(format!("? {} waiting", self.waiting));
}
if self.idle > 0 {
parts.push(format!("- {} idle", self.idle));
}
if self.completed > 0 {
parts.push(format!("✓ {} done", self.completed));
}
if self.errored > 0 {
parts.push(format!("! {} err", self.errored));
}
if self.spawning > 0 {
parts.push(format!("○ {} starting", self.spawning));
}
parts.join(" ")
}test_status_bar_format_all_states function · rust · L633-L648 (16 LOC)src/agent/manager.rs
fn test_status_bar_format_all_states() {
let counts = StateCounts {
running: 2,
waiting: 1,
idle: 1,
completed: 1,
errored: 1,
spawning: 0,
};
let text = counts.format_status_bar();
assert!(text.contains("● 2 running"));
assert!(text.contains("? 1 waiting"));
assert!(text.contains("- 1 idle"));
assert!(text.contains("✓ 1 done"));
assert!(text.contains("! 1 err"));
}test_status_bar_format_empty function · rust · L651-L654 (4 LOC)src/agent/manager.rs
fn test_status_bar_format_empty() {
let counts = StateCounts::default();
assert_eq!(counts.format_status_bar(), "");
}test_status_bar_format_running_only function · rust · L657-L663 (7 LOC)src/agent/manager.rs
fn test_status_bar_format_running_only() {
let counts = StateCounts {
running: 3,
..Default::default()
};
assert_eq!(counts.format_status_bar(), "● 3 running");
}test_status_bar_format_spawning function · rust · L666-L672 (7 LOC)src/agent/manager.rs
fn test_status_bar_format_spawning() {
let counts = StateCounts {
spawning: 2,
..Default::default()
};
assert_eq!(counts.format_status_bar(), "○ 2 starting");
}test_status_bar_format_order function · rust · L675-L686 (12 LOC)src/agent/manager.rs
fn test_status_bar_format_order() {
let counts = StateCounts {
running: 1,
spawning: 1,
..Default::default()
};
let text = counts.format_status_bar();
// Running should appear before spawning
let running_pos = text.find("running").unwrap();
let spawning_pos = text.find("starting").unwrap();
assert!(running_pos < spawning_pos);
}test_spawn_and_kill_agent function · rust · L691-L724 (34 LOC)src/agent/manager.rs
async fn test_spawn_and_kill_agent() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
let id = manager
.spawn(
"test-agent".into(),
"test-project".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
// Agent should exist
assert!(manager.get(id).is_some());
assert_eq!(manager.agent_count(), 1);
// Kill it
manager.kill(id).unwrap();
// Agent should be in Errored state (killed by user)
let handle = manager.get(id).unwrap();
assert!(handle.state().is_terminal());
}test_spawn_limit_enforcement function · rust · L727-L775 (49 LOC)src/agent/manager.rs
async fn test_spawn_limit_enforcement() {
let mut config = MaestroConfig::default();
config.global.max_agents = 2;
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
// Spawn 2 agents (at limit)
manager
.spawn(
"a1".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager
.spawn(
"a2".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
// Repobility · severity-and-effort ranking · https://repobility.com
test_duplicate_name_rejected function · rust · L778-L825 (48 LOC)src/agent/manager.rs
async fn test_duplicate_name_rejected() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
manager
.spawn(
"agent".into(),
"project".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
// Same name + project should fail
let result = manager.spawn(
"agent".into(),
"project".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
);
assert!(result.is_err());
// Same name + different project should test_display_order_grouping function · rust · L828-L880 (53 LOC)src/agent/manager.rs
async fn test_display_order_grouping() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
manager
.spawn(
"a1".into(),
"proj-a".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager
.spawn(
"b1".into(),
"proj-b".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager
.spawn(
"a2".into(),
"test_kill_nonexistent_agent function · rust · L883-L890 (8 LOC)src/agent/manager.rs
async fn test_kill_nonexistent_agent() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let result = manager.kill(AgentId::new());
assert!(result.is_err());
}test_restart_agent function · rust · L893-L925 (33 LOC)src/agent/manager.rs
async fn test_restart_agent() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
let old_id = manager
.spawn(
"test-agent".into(),
"test-project".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let new_id = manager.restart(old_id, pty_size).unwrap();
// Old agent should be gone
assert!(manager.get(old_id).is_none());
// New agent should exist
assert!(manager.get(new_id).is_some());
assert_eq!(manager.get(new_id).unwrap().name(), "test-agent");
assert_eq!(manager.agent_count(), 1);test_state_counts function · rust · L928-L967 (40 LOC)src/agent/manager.rs
async fn test_state_counts() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
// Spawn two agents (both start in Spawning state)
manager
.spawn(
"a1".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager
.spawn(
"a2".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let counts = manager.state_counts(test_all_agent_ids_ordered function · rust · L970-L1009 (40 LOC)src/agent/manager.rs
async fn test_all_agent_ids_ordered() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
let id1 = manager
.spawn(
"a1".into(),
"p1".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let id2 = manager
.spawn(
"a2".into(),
"p2".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let ordered = manager.all_agent_ids_ordered();
assert_test_find_by_name function · rust · L1012-L1039 (28 LOC)src/agent/manager.rs
async fn test_find_by_name() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
let id = manager
.spawn(
"my-agent".into(),
"my-project".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
assert_eq!(manager.find_by_name("my-project", "my-agent"), Some(id));
assert_eq!(manager.find_by_name("my-project", "other"), None);
assert_eq!(manager.find_by_name("other-project", "my-agent"), None);
}test_add_empty_project function · rust · L1042-L1053 (12 LOC)src/agent/manager.rs
async fn test_add_empty_project() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
manager.add_empty_project("new-project").unwrap();
let groups = manager.agents_by_project();
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].0, "new-project");
assert!(groups[0].1.is_empty());
}Want this analysis on your repo? https://repobility.com/scan/
test_add_duplicate_project_rejected function · rust · L1056-L1064 (9 LOC)src/agent/manager.rs
async fn test_add_duplicate_project_rejected() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
manager.add_empty_project("proj").unwrap();
let result = manager.add_empty_project("proj");
assert!(result.is_err());
}test_spawn_into_empty_project function · rust · L1067-L1097 (31 LOC)src/agent/manager.rs
async fn test_spawn_into_empty_project() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
manager.add_empty_project("proj").unwrap();
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
let id = manager
.spawn(
"agent1".into(),
"proj".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let groups = manager.agents_by_project();
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].0, "proj");
assert_eq!(groups[0].1.len(), 1);
assert_eq!(groups[0].1[0], id);
}test_kill_all function · rust · L1100-L1141 (42 LOC)src/agent/manager.rs
async fn test_kill_all() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
manager
.spawn(
"a1".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager
.spawn(
"a2".into(),
"p".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
manager.kill_all();
// All agents should be in terminal state
for handle in manatest_display_order_after_restart function · rust · L1144-L1187 (44 LOC)src/agent/manager.rs
async fn test_display_order_after_restart() {
let config = MaestroConfig::default();
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = AgentManager::new(&config, tx);
let pty_size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
manager
.spawn(
"a1".into(),
"proj".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
let id2 = manager
.spawn(
"a2".into(),
"proj".into(),
"cat".into(),
vec![],
std::env::temp_dir(),
HashMap::new(),
pty_size,
)
.unwrap();
// Restart a2 — should remove old and add new
let new_new function · rust · L34-L36 (3 LOC)src/agent/mod.rs
pub fn new() -> Self {
Self(Uuid::new_v4())
}as_uuid function · rust · L39-L41 (3 LOC)src/agent/mod.rs
pub fn as_uuid(&self) -> &Uuid {
&self.0
}default function · rust · L45-L47 (3 LOC)src/agent/mod.rs
fn default() -> Self {
Self::new()
}fmt function · rust · L51-L55 (5 LOC)src/agent/mod.rs
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Short 8-char prefix for compact display in the UI.
let s = self.0.to_string();
write!(f, "{}", &s[..8])
}Repobility — same analyzer, your code, free for public repos · /scan/
from function · rust · L59-L61 (3 LOC)src/agent/mod.rs
fn from(uuid: Uuid) -> Self {
Self(uuid)
}agent_id_uniqueness function · rust · L69-L73 (5 LOC)src/agent/mod.rs
fn agent_id_uniqueness() {
let a = AgentId::new();
let b = AgentId::new();
assert_ne!(a, b);
}agent_id_display_is_short function · rust · L76-L80 (5 LOC)src/agent/mod.rs
fn agent_id_display_is_short() {
let id = AgentId::new();
let display = format!("{id}");
assert_eq!(display.len(), 8);
}