use super::super::App;
impl App {
pub(crate) fn handle_swarm_command(&mut self, input: &str) -> Option<String> {
if input == "/detach" {
if matches!(
self.state.view_mode,
crate::tui::state::ViewMode::WorkerAttached { .. }
) {
self.state.detach_worker();
return Some("Detached from worker.".to_string());
}
return Some("Not attached to any worker.".to_string());
}
if let Some(agent_id) = input.strip_prefix("/attach ").map(str::trim) {
if agent_id.is_empty() {
return Some("Usage: /attach <agent_id>".to_string());
}
let exists = self
.state
.swarm_status
.as_ref()
.map(|h| h.agents.iter().any(|a| a.agent_id == agent_id))
.unwrap_or(false);
if !exists {
return Some(format!("Worker `{agent_id}` not found."));
}
self.state.attach_worker(agent_id);
return Some(format!(
"Attached to worker `{agent_id}`. Press Esc to detach."
));
}
let kb = self.swarm_knowledge.as_ref()?;
if let Some(agent_id) = input.strip_prefix("/cancel-worker ").map(str::trim) {
if agent_id.is_empty() {
return Some("Usage: /cancel-worker <agent_id>".to_string());
}
let kb = kb.clone();
let id = agent_id.to_string();
tokio::spawn(async move {
kb.cancel_worker(&id).await;
});
return Some(format!("Cancelling worker `{agent_id}`..."));
}
if let Some(rest) = input.strip_prefix("/redirect-worker ").map(str::trim) {
let (agent_id, instruction) = rest.split_once(' ').unwrap_or((rest, ""));
if agent_id.is_empty() || instruction.is_empty() {
return Some("Usage: /redirect-worker <agent_id> <new focus>".to_string());
}
let kb = kb.clone();
let id = agent_id.to_string();
let instr = crate::agent::swarm::knowledge::WorkerInstruction::Redirect {
new_focus: instruction.to_string(),
};
tokio::spawn(async move {
kb.send_instruction(&id, instr).await;
});
return Some(format!("Redirecting worker `{agent_id}`..."));
}
if let Some(rest) = input.strip_prefix("/hint-worker ").map(str::trim) {
let (agent_id, text) = rest.split_once(' ').unwrap_or((rest, ""));
if agent_id.is_empty() || text.is_empty() {
return Some("Usage: /hint-worker <agent_id> <hint text>".to_string());
}
let kb = kb.clone();
let id = agent_id.to_string();
let instr = crate::agent::swarm::knowledge::WorkerInstruction::Hint {
text: text.to_string(),
};
tokio::spawn(async move {
kb.send_instruction(&id, instr).await;
});
return Some(format!("Sent hint to worker `{agent_id}`."));
}
if let Some(rest) = input.strip_prefix("/pause-worker ").map(str::trim) {
if rest.is_empty() {
return Some("Usage: /pause-worker <agent_id>".to_string());
}
let kb = kb.clone();
let id = rest.to_string();
let instr = crate::agent::swarm::knowledge::WorkerInstruction::Pause;
tokio::spawn(async move {
kb.send_instruction(&id, instr).await;
});
return Some(format!("Pausing worker `{rest}`..."));
}
if let Some(rest) = input.strip_prefix("/resume-worker ").map(str::trim) {
if rest.is_empty() {
return Some("Usage: /resume-worker <agent_id>".to_string());
}
let kb = kb.clone();
let id = rest.to_string();
let instr = crate::agent::swarm::knowledge::WorkerInstruction::Resume;
tokio::spawn(async move {
kb.send_instruction(&id, instr).await;
});
return Some(format!("Resuming worker `{rest}`..."));
}
if let Some(rest) = input.strip_prefix("/extend-worker ").map(str::trim) {
let parts: Vec<&str> = rest.splitn(2, ' ').collect();
let agent_id = parts.first().copied().unwrap_or("");
let extra: u32 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(10);
if agent_id.is_empty() {
return Some("Usage: /extend-worker <agent_id> [iterations]".to_string());
}
let kb = kb.clone();
let id = agent_id.to_string();
tokio::spawn(async move {
kb.extend_worker(&id, extra).await;
});
return Some(format!(
"Extending worker `{agent_id}` by {extra} iterations."
));
}
if input == "/workers" || input == "/list-workers" {
let kb = kb.clone();
if let Some(ref hive) = self.state.swarm_status {
let lines: Vec<String> = hive
.agents
.iter()
.map(|a| {
let status = match &a.status {
crate::tui::state::SwarmAgentStatus::Pending => "⏳ pending",
crate::tui::state::SwarmAgentStatus::Running => "▶ running",
crate::tui::state::SwarmAgentStatus::Paused => "⏸ paused",
crate::tui::state::SwarmAgentStatus::Completed { success } => {
if *success {
"✓ done"
} else {
"✗ failed"
}
}
};
let tool_info = a
.current_tool
.as_deref()
.map(|t| format!(" ({})", t))
.unwrap_or_default();
format!(
" {} [{}] — {}{} | {} tools",
a.agent_id, status, a.task_preview, tool_info, a.tool_calls
)
})
.collect();
return Some(format!("Active workers:\n{}", lines.join("\n")));
}
let _ = kb;
return Some("No active swarm.".to_string());
}
None
}
}