Skip to main content

ag_agent/model/
permission.rs

1use std::fmt;
2use std::str::FromStr;
3
4/// Supported permission mode values for agent execution workflows.
5#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
6pub enum PermissionMode {
7    /// Allows the agent to edit files automatically within its sandbox.
8    #[default]
9    AutoEdit,
10    /// Restricts the agent to repository inspection without filesystem writes
11    /// or mutating command approvals.
12    ReadOnly,
13}
14
15impl PermissionMode {
16    /// Ordered permission-mode options shown by interactive selectors.
17    pub const ALL: [PermissionMode; 2] = [PermissionMode::AutoEdit, PermissionMode::ReadOnly];
18
19    /// Returns the wire label used for persistence and provider invocation.
20    pub fn label(self) -> &'static str {
21        match self {
22            Self::AutoEdit => "auto_edit",
23            Self::ReadOnly => "read_only",
24        }
25    }
26
27    /// Returns the user-facing label shown in the UI.
28    pub fn display_label(self) -> &'static str {
29        match self {
30            Self::AutoEdit => "Auto Edit",
31            Self::ReadOnly => "Read Only",
32        }
33    }
34
35    /// Returns whether the provider must deny repository mutations.
36    pub fn is_read_only(self) -> bool {
37        self == Self::ReadOnly
38    }
39}
40
41impl fmt::Display for PermissionMode {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        write!(f, "{}", self.label())
44    }
45}
46
47impl FromStr for PermissionMode {
48    type Err = String;
49
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        match s {
52            "auto_edit" => Ok(PermissionMode::AutoEdit),
53            "read_only" => Ok(PermissionMode::ReadOnly),
54            _ => Err(format!("Unknown permission mode: {s}")),
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_from_str_accepts_supported_modes() {
65        // Arrange
66        let permission_modes = ["auto_edit", "read_only"];
67
68        // Act
69        let parsed_permission_modes = permission_modes.map(PermissionMode::from_str);
70
71        // Assert
72        assert_eq!(
73            parsed_permission_modes,
74            [Ok(PermissionMode::AutoEdit), Ok(PermissionMode::ReadOnly)]
75        );
76    }
77
78    #[test]
79    fn test_from_str_rejects_removed_permission_modes() {
80        // Arrange
81        let removed_mode = "autonomous";
82
83        // Act
84        let parsed_permission_mode = PermissionMode::from_str(removed_mode);
85
86        // Assert
87        assert_eq!(
88            parsed_permission_mode,
89            Err("Unknown permission mode: autonomous".to_string())
90        );
91    }
92
93    #[test]
94    fn test_default_uses_auto_edit_mode() {
95        // Arrange, Act
96        let permission_mode = PermissionMode::default();
97
98        // Assert
99        assert_eq!(permission_mode, PermissionMode::AutoEdit);
100    }
101
102    #[test]
103    fn test_label_and_display_label_return_persisted_and_user_facing_text() {
104        // Arrange
105        let permission_modes = [PermissionMode::AutoEdit, PermissionMode::ReadOnly];
106
107        // Act
108        let labels = permission_modes.map(PermissionMode::label);
109        let display_labels = permission_modes.map(PermissionMode::display_label);
110        let read_only = permission_modes.map(PermissionMode::is_read_only);
111
112        // Assert
113        assert_eq!(labels, ["auto_edit", "read_only"]);
114        assert_eq!(display_labels, ["Auto Edit", "Read Only"]);
115        assert_eq!(read_only, [false, true]);
116    }
117
118    #[test]
119    fn test_display_uses_persisted_label() {
120        // Arrange
121        let permission_mode = PermissionMode::AutoEdit;
122
123        // Act
124        let formatted = permission_mode.to_string();
125
126        // Assert
127        assert_eq!(formatted, "auto_edit");
128    }
129}