claude_agent/tools/
access.rs

1//! Tool access control definitions.
2
3use std::collections::HashSet;
4
5/// Controls which tools are available to the agent.
6#[derive(Debug, Clone, Default)]
7pub enum ToolAccess {
8    /// No tools are allowed.
9    None,
10    /// All tools are allowed.
11    #[default]
12    All,
13    /// Only the specified tools are allowed.
14    Only(HashSet<String>),
15    /// All tools except the specified ones are allowed.
16    Except(HashSet<String>),
17}
18
19impl ToolAccess {
20    pub fn all() -> Self {
21        Self::All
22    }
23
24    pub fn none() -> Self {
25        Self::None
26    }
27
28    pub fn only(tools: impl IntoIterator<Item = impl Into<String>>) -> Self {
29        Self::Only(tools.into_iter().map(Into::into).collect())
30    }
31
32    pub fn except(tools: impl IntoIterator<Item = impl Into<String>>) -> Self {
33        Self::Except(tools.into_iter().map(Into::into).collect())
34    }
35
36    #[inline]
37    pub fn is_allowed(&self, tool_name: &str) -> bool {
38        match self {
39            Self::None => false,
40            Self::All => true,
41            Self::Only(allowed) => allowed.contains(tool_name),
42            Self::Except(denied) => !denied.contains(tool_name),
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn test_all_allows_everything() {
53        let access = ToolAccess::all();
54        assert!(access.is_allowed("Read"));
55        assert!(access.is_allowed("Write"));
56        assert!(access.is_allowed("AnythingElse"));
57    }
58
59    #[test]
60    fn test_none_denies_everything() {
61        let access = ToolAccess::none();
62        assert!(!access.is_allowed("Read"));
63        assert!(!access.is_allowed("Write"));
64    }
65
66    #[test]
67    fn test_only_allows_specified() {
68        let access = ToolAccess::only(["Read", "Write"]);
69        assert!(access.is_allowed("Read"));
70        assert!(access.is_allowed("Write"));
71        assert!(!access.is_allowed("Bash"));
72        assert!(!access.is_allowed("Edit"));
73    }
74
75    #[test]
76    fn test_except_denies_specified() {
77        let access = ToolAccess::except(["Bash", "KillShell"]);
78        assert!(access.is_allowed("Read"));
79        assert!(access.is_allowed("Write"));
80        assert!(!access.is_allowed("Bash"));
81        assert!(!access.is_allowed("KillShell"));
82    }
83}