diff --git a/rust/crates/runtime/src/config.rs b/rust/crates/runtime/src/config.rs index 368e7c5..9601eb5 100644 --- a/rust/crates/runtime/src/config.rs +++ b/rust/crates/runtime/src/config.rs @@ -42,6 +42,7 @@ pub struct RuntimeFeatureConfig { oauth: Option, model: Option, permission_mode: Option, + permission_rules: RuntimePermissionRuleConfig, sandbox: SandboxConfig, } @@ -49,6 +50,14 @@ pub struct RuntimeFeatureConfig { pub struct RuntimeHookConfig { pre_tool_use: Vec, post_tool_use: Vec, + post_tool_use_failure: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct RuntimePermissionRuleConfig { + allow: Vec, + deny: Vec, + ask: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Default)] @@ -235,6 +244,7 @@ impl ConfigLoader { oauth: parse_optional_oauth_config(&merged_value, "merged settings.oauth")?, model: parse_optional_model(&merged_value), permission_mode: parse_optional_permission_mode(&merged_value)?, + permission_rules: parse_optional_permission_rules(&merged_value)?, sandbox: parse_optional_sandbox_config(&merged_value)?, }; @@ -344,6 +354,11 @@ impl RuntimeFeatureConfig { self.permission_mode } + #[must_use] + pub fn permission_rules(&self) -> &RuntimePermissionRuleConfig { + &self.permission_rules + } + #[must_use] pub fn sandbox(&self) -> &SandboxConfig { &self.sandbox @@ -352,10 +367,15 @@ impl RuntimeFeatureConfig { impl RuntimeHookConfig { #[must_use] - pub fn new(pre_tool_use: Vec, post_tool_use: Vec) -> Self { + pub fn new( + pre_tool_use: Vec, + post_tool_use: Vec, + post_tool_use_failure: Vec, + ) -> Self { Self { pre_tool_use, post_tool_use, + post_tool_use_failure, } } @@ -368,6 +388,33 @@ impl RuntimeHookConfig { pub fn post_tool_use(&self) -> &[String] { &self.post_tool_use } + + #[must_use] + pub fn post_tool_use_failure(&self) -> &[String] { + &self.post_tool_use_failure + } +} + +impl RuntimePermissionRuleConfig { + #[must_use] + pub fn new(allow: Vec, deny: Vec, ask: Vec) -> Self { + Self { allow, deny, ask } + } + + #[must_use] + pub fn allow(&self) -> &[String] { + &self.allow + } + + #[must_use] + pub fn deny(&self) -> &[String] { + &self.deny + } + + #[must_use] + pub fn ask(&self) -> &[String] { + &self.ask + } } impl McpConfigCollection { @@ -481,6 +528,32 @@ fn parse_optional_hooks_config(root: &JsonValue) -> Result Result { + let Some(object) = root.as_object() else { + return Ok(RuntimePermissionRuleConfig::default()); + }; + let Some(permissions) = object.get("permissions").and_then(JsonValue::as_object) else { + return Ok(RuntimePermissionRuleConfig::default()); + }; + + Ok(RuntimePermissionRuleConfig { + allow: optional_string_array(permissions, "allow", "merged settings.permissions")? + .unwrap_or_default(), + deny: optional_string_array(permissions, "deny", "merged settings.permissions")? + .unwrap_or_default(), + ask: optional_string_array(permissions, "ask", "merged settings.permissions")? + .unwrap_or_default(), }) }