diff --git a/hive-c0re/src/tool_groups.rs b/hive-c0re/src/tool_groups.rs index 1d894e59..c9341709 100644 --- a/hive-c0re/src/tool_groups.rs +++ b/hive-c0re/src/tool_groups.rs @@ -26,8 +26,6 @@ use std::collections::BTreeMap; use std::path::PathBuf; -use anyhow::Context as _; - const TOOL_GROUPS_FILE: &str = "tool-groups.json"; #[must_use] @@ -56,9 +54,9 @@ pub fn groups_for(name: &str) -> Vec { } /// Persist the full tool-groups map. Sorted JSON output keeps diffs -/// minimal. Use `set_groups` (or `remove_agent`) from outside this -/// module — they go through the validated write path. -fn write(map: &BTreeMap>) -> std::io::Result<()> { +/// minimal. Best-effort — returns `io::Error` so callers decide +/// whether to abort or log. +pub fn write(map: &BTreeMap>) -> std::io::Result<()> { let path = tool_groups_path(); if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; @@ -68,46 +66,16 @@ fn write(map: &BTreeMap>) -> std::io::Result<()> { std::fs::write(&path, format!("{text}\n")) } -/// Validate a slice of group name strings against `ToolGroup::ALL`. -/// Returns `Ok(())` when all names are known, or `Err` listing the -/// unrecognised names so callers can surface a useful error message. -fn validate_groups(groups: &[String]) -> anyhow::Result<()> { - let valid: std::collections::BTreeSet<&str> = - hive_sh4re::ToolGroup::ALL.iter().map(|g| g.as_str()).collect(); - let unknown: Vec<&str> = groups - .iter() - .map(String::as_str) - .filter(|s| !valid.contains(s)) - .collect(); - if unknown.is_empty() { - Ok(()) - } else { - anyhow::bail!( - "unknown tool group(s): {}; valid names are: {}", - unknown.join(", "), - hive_sh4re::ToolGroup::ALL - .iter() - .map(|g| g.as_str()) - .collect::>() - .join(", ") - ) - } -} - /// Set the tool groups for one agent and persist the map. An empty /// `groups` vec removes the entry (agent reverts to role default). -/// Returns an error if any name is not in `ToolGroup::ALL`. -pub fn set_groups(name: &str, groups: &[String]) -> anyhow::Result<()> { - if !groups.is_empty() { - validate_groups(groups)?; - } +pub fn set_groups(name: &str, groups: &[String]) -> std::io::Result<()> { let mut current = read(); if groups.is_empty() { current.remove(name); } else { current.insert(name.to_owned(), groups.to_vec()); } - write(¤t).with_context(|| format!("write tool-groups for {name}")) + write(¤t) } /// Drop the entry for an agent that is being destroyed. Idempotent.