diff --git a/server/src/http/bot_command.rs b/server/src/http/bot_command.rs index 7081f27a..3e7f7e8c 100644 --- a/server/src/http/bot_command.rs +++ b/server/src/http/bot_command.rs @@ -81,6 +81,7 @@ async fn dispatch_command( "start" => dispatch_start(args, project_root, agents).await, "delete" => dispatch_delete(args, project_root, agents).await, "rebuild" => dispatch_rebuild(project_root, agents).await, + "rmtree" => dispatch_rmtree(args, project_root, agents).await, "timer" => dispatch_timer(args, project_root).await, "htop" => dispatch_htop(args, agents).await, // All other commands go through the synchronous command registry. @@ -204,6 +205,24 @@ async fn dispatch_delete( .await } +async fn dispatch_rmtree( + args: &str, + project_root: &std::path::Path, + agents: &Arc, +) -> String { + let number_str = args.trim(); + if number_str.is_empty() || !number_str.chars().all(|c| c.is_ascii_digit()) { + return "Usage: `/rmtree ` (e.g. `/rmtree 42`)".to_string(); + } + crate::chat::transport::matrix::rmtree::handle_rmtree( + "web-ui", + number_str, + project_root, + agents, + ) + .await +} + async fn dispatch_rebuild( project_root: &std::path::Path, agents: &Arc, @@ -439,6 +458,62 @@ mod tests { ); } + // -- rmtree ---------------------------------------------------------------- + + #[tokio::test] + async fn rmtree_without_number_returns_usage() { + let dir = TempDir::new().unwrap(); + let api = test_api(&dir); + let body = BotCommandRequest { + command: "rmtree".to_string(), + args: String::new(), + }; + let result = api.run_command(Json(body)).await; + assert!(result.is_ok()); + let resp = result.unwrap().0; + assert!( + resp.response.contains("Usage"), + "expected usage hint for bare /rmtree: {}", + resp.response + ); + } + + #[tokio::test] + async fn rmtree_with_non_numeric_arg_returns_usage() { + let dir = TempDir::new().unwrap(); + let api = test_api(&dir); + let body = BotCommandRequest { + command: "rmtree".to_string(), + args: "foo".to_string(), + }; + let result = api.run_command(Json(body)).await; + assert!(result.is_ok()); + let resp = result.unwrap().0; + assert!( + resp.response.contains("Usage"), + "expected usage hint for /rmtree foo: {}", + resp.response + ); + } + + #[tokio::test] + async fn rmtree_does_not_return_unknown_command() { + let dir = TempDir::new().unwrap(); + let api = test_api(&dir); + let body = BotCommandRequest { + command: "rmtree".to_string(), + args: "999".to_string(), + }; + let result = api.run_command(Json(body)).await; + assert!(result.is_ok()); + let resp = result.unwrap().0; + assert!( + !resp.response.contains("Unknown command"), + "/rmtree should not return 'Unknown command': {}", + resp.response + ); + } + // -- htop bot-command path (regression: htop must remain in command registry) -- #[test]