huskies: merge 629_refactor_migrate_commanddispatch_and_commandcontext_to_services_bundle
This commit is contained in:
@@ -34,7 +34,7 @@ pub(super) fn handle_setup(ctx: &CommandContext) -> Option<String> {
|
||||
/// This mirrors `wizard_generate` (with no content) from the MCP tools, making
|
||||
/// the interview flow accessible from chat transports (Matrix, Slack, WhatsApp).
|
||||
fn wizard_generate_reply(ctx: &CommandContext) -> String {
|
||||
let root = ctx.project_root;
|
||||
let root = ctx.effective_root();
|
||||
let mut state = match WizardState::load(root) {
|
||||
Some(s) => s,
|
||||
None => return "No wizard active.".to_string(),
|
||||
@@ -63,10 +63,10 @@ fn wizard_generate_reply(ctx: &CommandContext) -> String {
|
||||
/// If no wizard state exists, automatically initializes it so the user does
|
||||
/// not need to run `huskies init` manually.
|
||||
fn wizard_status_reply(ctx: &CommandContext) -> String {
|
||||
if WizardState::load(ctx.project_root).is_none() {
|
||||
WizardState::init_if_missing(ctx.project_root);
|
||||
if WizardState::load(ctx.effective_root()).is_none() {
|
||||
WizardState::init_if_missing(ctx.effective_root());
|
||||
}
|
||||
match WizardState::load(ctx.project_root) {
|
||||
match WizardState::load(ctx.effective_root()) {
|
||||
Some(state) => format_wizard_state(&state),
|
||||
None => "Unable to initialize setup wizard. Ensure the `.huskies/` directory exists."
|
||||
.to_string(),
|
||||
@@ -75,7 +75,7 @@ fn wizard_status_reply(ctx: &CommandContext) -> String {
|
||||
|
||||
/// Confirm the current wizard step, writing any staged content to disk.
|
||||
fn wizard_confirm_reply(ctx: &CommandContext) -> String {
|
||||
let root = ctx.project_root;
|
||||
let root = ctx.effective_root();
|
||||
let mut state = match WizardState::load(root) {
|
||||
Some(s) => s,
|
||||
None => return "No wizard active.".to_string(),
|
||||
@@ -124,7 +124,7 @@ fn wizard_confirm_reply(ctx: &CommandContext) -> String {
|
||||
|
||||
/// Skip the current wizard step without writing any file.
|
||||
fn wizard_skip_reply(ctx: &CommandContext) -> String {
|
||||
let root = ctx.project_root;
|
||||
let root = ctx.effective_root();
|
||||
let mut state = match WizardState::load(root) {
|
||||
Some(s) => s,
|
||||
None => return "No wizard active.".to_string(),
|
||||
@@ -157,7 +157,7 @@ fn wizard_skip_reply(ctx: &CommandContext) -> String {
|
||||
|
||||
/// Discard staged content and reset the current step to pending.
|
||||
fn wizard_retry_reply(ctx: &CommandContext) -> String {
|
||||
let root = ctx.project_root;
|
||||
let root = ctx.effective_root();
|
||||
let mut state = match WizardState::load(root) {
|
||||
Some(s) => s,
|
||||
None => return "No wizard active.".to_string(),
|
||||
@@ -189,33 +189,23 @@ fn wizard_retry_reply(ctx: &CommandContext) -> String {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::io::wizard::WizardState;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn make_ctx<'a>(
|
||||
args: &'a str,
|
||||
project_root: &'a std::path::Path,
|
||||
agents: &'a Arc<crate::agents::AgentPool>,
|
||||
ambient_rooms: &'a Arc<Mutex<HashSet<String>>>,
|
||||
services: &'a crate::services::Services,
|
||||
) -> CommandContext<'a> {
|
||||
CommandContext {
|
||||
bot_name: "Bot",
|
||||
args,
|
||||
project_root,
|
||||
agents,
|
||||
ambient_rooms,
|
||||
room_id: "!test:example.com",
|
||||
}
|
||||
CommandContext::new_test(services, args, "!test:example.com", project_root)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setup_no_wizard_auto_initializes() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4000));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
// Bot should auto-initialize and return wizard status, not ask user to run huskies init.
|
||||
assert!(result.contains("Setup wizard"));
|
||||
@@ -229,9 +219,9 @@ mod tests {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
WizardState::init_if_missing(dir.path());
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4001));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("Setup wizard"));
|
||||
}
|
||||
@@ -241,9 +231,9 @@ mod tests {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
WizardState::init_if_missing(dir.path());
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4002));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("skip", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("skip", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("skipped"));
|
||||
let state = WizardState::load(dir.path()).unwrap();
|
||||
@@ -255,9 +245,9 @@ mod tests {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
WizardState::init_if_missing(dir.path());
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4003));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("confirm", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("confirm", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("confirmed"));
|
||||
let state = WizardState::load(dir.path()).unwrap();
|
||||
@@ -279,9 +269,9 @@ mod tests {
|
||||
);
|
||||
state.save(dir.path()).unwrap();
|
||||
}
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4004));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("retry", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("retry", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("reset"));
|
||||
let state = WizardState::load(dir.path()).unwrap();
|
||||
@@ -294,9 +284,9 @@ mod tests {
|
||||
#[test]
|
||||
fn setup_unknown_sub_command_returns_usage() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4005));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("foobar", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("foobar", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("Unknown sub-command"));
|
||||
assert!(result.contains("Usage"));
|
||||
@@ -307,9 +297,9 @@ mod tests {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
WizardState::init_if_missing(dir.path());
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4006));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("generate", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("generate", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("generating"));
|
||||
let state = WizardState::load(dir.path()).unwrap();
|
||||
@@ -325,9 +315,9 @@ mod tests {
|
||||
// Bare project — only scaffolding files
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
WizardState::init_if_missing(dir.path());
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4007));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("generate", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("generate", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("bare project"));
|
||||
assert!(result.contains("Ask the user"));
|
||||
@@ -336,9 +326,9 @@ mod tests {
|
||||
#[test]
|
||||
fn setup_generate_no_wizard_returns_error() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let agents = Arc::new(crate::agents::AgentPool::new_test(4008));
|
||||
let rooms = Arc::new(Mutex::new(HashSet::new()));
|
||||
let ctx = make_ctx("generate", dir.path(), &agents, &rooms);
|
||||
let services =
|
||||
crate::services::Services::new_test(dir.path().to_path_buf(), "Bot".to_string());
|
||||
let ctx = make_ctx("generate", dir.path(), &services);
|
||||
let result = handle_setup(&ctx).unwrap();
|
||||
assert!(result.contains("No wizard active"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user