use std::collections::HashSet;
use std::path::Path;
use crate::adapter::{AdapterKind, AgentAdapter};
use crate::config;
use crate::error::Result;
use super::{home_dir, render_table};
pub fn cmd_agent_list(repo_root: &Path, global: bool) -> Result<()> {
let config_root = if global {
home_dir()?
} else {
repo_root.to_path_buf()
};
let config = if global {
config::read_global_config(&config_root)?
} else {
config::read_config(&config_root)?
};
let registered: HashSet<&str> = config.agents.iter().map(|s| s.as_str()).collect();
let table_rows: Vec<Vec<String>> = AdapterKind::all()
.iter()
.map(|a| {
vec![
a.id().to_string(),
a.supported_agents().join(", "),
a.kinds_supported()
.iter()
.map(|ct| ct.to_string())
.collect::<Vec<_>>()
.join(", "),
if registered.contains(a.id()) {
"yes".to_string()
} else {
String::new()
},
if config.default_agent == a.id() {
"yes".to_string()
} else {
String::new()
},
]
})
.collect();
println!(
"{}",
render_table(
&[
"HARNESS",
"HARNESSES SUPPORTED",
"CAPABILITIES",
"REGISTERED",
"DEFAULT",
],
&table_rows
)
);
println!(
"\n REGISTERED = available for Tuff operations in this {} config",
if global { "global" } else { "project" }
);
println!(
" DEFAULT = used when --harness is omitted ({})",
if global { "global" } else { "project" }
);
Ok(())
}
pub fn cmd_agent_add(repo_root: &Path, id: &str) -> Result<()> {
let adapter = AdapterKind::from_id(id).ok_or_else(|| {
crate::error::TuffError::usage(format!("unknown harness '{}'", id,))
.with_hint("run 'tuff harness list' to see available harnesses")
})?;
let mut config = config::read_config(repo_root)?;
adapter.ensure_project_dir(repo_root)?;
if config.agents.contains(&adapter.id().to_string()) {
println!("harness '{}' is already registered", id);
return Ok(());
}
config.agents.push(adapter.id().to_string());
config::write_config(repo_root, &config)?;
println!(
"registered harness '{}' ({})",
adapter.id(),
adapter.display_name()
);
Ok(())
}
pub fn cmd_agent_remove(repo_root: &Path, id: &str) -> Result<()> {
let adapter = AdapterKind::from_id(id).ok_or_else(|| {
crate::error::TuffError::usage(format!("unknown harness '{}'", id,))
.with_hint("run 'tuff harness list' to see available harnesses")
})?;
let mut config = config::read_config(repo_root)?;
let was_registered = config.agents.contains(&adapter.id().to_string());
config.agents.retain(|t| t != adapter.id());
config::write_config(repo_root, &config)?;
if was_registered {
println!("unregistered harness '{}'", adapter.id());
} else {
println!("removed harness '{}'", adapter.id());
}
Ok(())
}
pub fn cmd_agent_set_default(repo_root: &Path, id: &str, global: bool) -> Result<()> {
let adapter = AdapterKind::from_id(id).ok_or_else(|| {
crate::error::TuffError::usage(format!("unknown harness '{}'", id,))
.with_hint("run 'tuff harness list' to see available harnesses")
})?;
let config_root = if global {
home_dir()?
} else {
repo_root.to_path_buf()
};
let mut config = if global {
config::read_global_config(&config_root)?
} else {
config::read_config(&config_root)?
};
config.default_agent = adapter.id().to_string();
if global {
config::write_global_config(&config_root, &config)?;
} else {
config::write_config(&config_root, &config)?;
}
println!(
"set default harness '{}' ({})",
adapter.id(),
if global { "global" } else { "project" }
);
Ok(())
}