From 30992aa0e33575e3e33fd0104b54976851177337 Mon Sep 17 00:00:00 2001 From: Hunter B Date: Sat, 13 Jun 2026 02:09:51 -0700 Subject: [PATCH] feat(tui): add /swarm WhaleFlow-backed multi-agent overlay (#3178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /swarm [N] is a high-fanout overlay on the current mode (Agent/Plan/YOLO), NOT a fourth mode. It mirrors the proven /agent command pattern: it emits a model instruction to decompose the task, fan out one headless sub-agent per subtask via agent_open (role/agent_type per subtask, max_depth N for nesting), run them concurrently, and synthesize from each worker's result SUMMARY (not its transcript) — the isolation pattern that keeps the orchestrator light. Registered with aliases fanout/qun; CmdSwarmDescription was already localized in all locales. Validated by the command-registry completeness tests (unique names/aliases, complete metadata); broad commands suite 431/0. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/tui/src/commands/groups/core/mod.rs | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/tui/src/commands/groups/core/mod.rs b/crates/tui/src/commands/groups/core/mod.rs index 8ae05be9..d07953d8 100644 --- a/crates/tui/src/commands/groups/core/mod.rs +++ b/crates/tui/src/commands/groups/core/mod.rs @@ -36,6 +36,7 @@ impl CommandGroup for CoreCommands { Box::new(FunctionCommand::new(&HOOKS_INFO, run_hooks)), Box::new(FunctionCommand::new(&SUBAGENTS_INFO, run_subagents)), Box::new(FunctionCommand::new(&AGENT_INFO, run_agent)), + Box::new(FunctionCommand::new(&SWARM_INFO, run_swarm)), Box::new(FunctionCommand::new(&LINKS_INFO, run_links)), Box::new(FunctionCommand::new(&FEEDBACK_INFO, run_feedback)), Box::new(FunctionCommand::new(&HF_INFO, run_hf)), @@ -123,6 +124,12 @@ static AGENT_INFO: CommandInfo = CommandInfo { usage: "/agent [N] ", description_id: MessageId::CmdAgentDescription, }; +static SWARM_INFO: CommandInfo = CommandInfo { + name: "swarm", + aliases: &["fanout", "qun"], + usage: "/swarm [N] ", + description_id: MessageId::CmdSwarmDescription, +}; static LINKS_INFO: CommandInfo = CommandInfo { name: "links", aliases: &["dashboard", "api", "lianjie"], @@ -230,6 +237,9 @@ fn run_subagents(app: &mut App, arg: Option<&str>) -> CommandResult { fn run_agent(app: &mut App, arg: Option<&str>) -> CommandResult { run_registered(app, "agent", arg) } +fn run_swarm(app: &mut App, arg: Option<&str>) -> CommandResult { + run_registered(app, "swarm", arg) +} fn run_links(app: &mut App, arg: Option<&str>) -> CommandResult { run_registered(app, "links", arg) } @@ -282,6 +292,7 @@ pub(in crate::commands) fn dispatch( "hooks" | "hook" | "gouzi" => hooks::hooks(app, arg), "subagents" | "agents" | "zhinengti" => core::subagents(app), "agent" | "daili" => agent(app, arg), + "swarm" | "fanout" | "qun" => swarm(app, arg), "links" | "dashboard" | "api" | "lianjie" => core::deepseek_links(app), "feedback" => feedback::feedback(app, arg), "hf" | "huggingface" => hf::hf(app, arg), @@ -361,6 +372,35 @@ pub fn agent(_app: &mut App, arg: Option<&str>) -> CommandResult { ) } +/// Run a WhaleFlow-backed multi-agent swarm: high-fanout headless sub-agents +/// over one task. This is an overlay on the current mode (Agent/Plan/YOLO), not +/// a fourth mode — it instructs the model to decompose and fan out, collecting +/// compact result summaries rather than child transcripts (#3178). +pub fn swarm(_app: &mut App, arg: Option<&str>) -> CommandResult { + let (max_depth, task) = match parse_depth_prefixed_arg(arg, 1) { + Ok(parsed) => parsed, + Err(message) => return CommandResult::error(message), + }; + let task = match task { + Some(task) if !task.trim().is_empty() => task.trim().to_string(), + _ => { + return CommandResult::error( + "Usage: /swarm [N] \n\n\ + Runs a multi-agent swarm: decomposes the task and fans out \ + headless sub-agents (recursive depth N, 0-3, default 1), then \ + synthesizes their results.", + ); + } + }; + let message = format!( + "Run a multi-agent swarm for this task: {task:?}. Decompose it into independent, parallelizable subtasks and open one headless sub-agent per subtask with `agent_open` (pass `max_depth: {max_depth}` for nested delegation, and an `agent_type`/role that fits each subtask — explore for research, review for verification, implementer for edits). Run them concurrently; collect each worker's result summary with `agent_eval` (summaries, not full transcripts) and synthesize a single answer. Keep the fanout proportional to the task, and verify any claimed side effects before reporting success." + ); + CommandResult::with_message_and_action( + format!("Dispatching a swarm at depth {max_depth}..."), + AppAction::SendMessage(message), + ) +} + fn parse_depth_prefixed_arg( arg: Option<&str>, default_depth: u32,