@@ -8,21 +8,21 @@ use super::file_ops::FileOpsTool;
88use super :: search:: SearchTool ;
99use super :: simple_search:: SimpleSearchTool ;
1010use super :: traits:: Tool ;
11+ use crate :: config:: PtyConfig ;
1112use crate :: config:: constants:: tools;
1213use crate :: config:: loader:: ConfigManager ;
1314use crate :: config:: types:: CapabilityLevel ;
14- use crate :: config:: PtyConfig ;
1515use crate :: gemini:: FunctionDeclaration ;
1616use crate :: tool_policy:: { ToolPolicy , ToolPolicyManager } ;
1717use crate :: tools:: ast_grep:: AstGrepEngine ;
1818use crate :: tools:: grep_search:: { GrepSearchManager , GrepSearchResult } ;
19- use anyhow:: { anyhow , Context , Result } ;
19+ use anyhow:: { Context , Result , anyhow } ;
2020use regex:: Regex ;
2121use serde:: { Deserialize , Serialize } ;
22- use serde_json:: { json , Value } ;
22+ use serde_json:: { Value , json } ;
2323use std:: path:: PathBuf ;
24- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
2524use std:: sync:: Arc ;
25+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
2626
2727/// Enhanced error handling for tool execution following Anthropic's best practices
2828/// Provides detailed error information and recovery suggestions
@@ -737,8 +737,12 @@ impl ToolRegistry {
737737 String :: new ( )
738738 } ;
739739
740+ let mut deny_regex = cfg. commands . deny_regex . clone ( ) ;
741+ if let Ok ( extra) = std:: env:: var ( "VTAGENT_COMMANDS_DENY_REGEX" ) {
742+ deny_regex. extend ( extra. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) ) ;
743+ }
740744 // Deny regex
741- for pat in & cfg . commands . deny_regex {
745+ for pat in & deny_regex {
742746 if Regex :: new ( pat)
743747 . ok ( )
744748 . map ( |re| re. is_match ( & cmd_text) )
@@ -747,8 +751,12 @@ impl ToolRegistry {
747751 return Err ( anyhow ! ( "Command denied by regex policy: {}" , pat) ) ;
748752 }
749753 }
754+ let mut deny_glob = cfg. commands . deny_glob . clone ( ) ;
755+ if let Ok ( extra) = std:: env:: var ( "VTAGENT_COMMANDS_DENY_GLOB" ) {
756+ deny_glob. extend ( extra. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) ) ;
757+ }
750758 // Deny glob (convert basic * to .*)
751- for pat in & cfg . commands . deny_glob {
759+ for pat in & deny_glob {
752760 let re = format ! ( "^{}$" , regex:: escape( pat) . replace( r"\*" , ".*" ) ) ;
753761 if Regex :: new ( & re)
754762 . ok ( )
@@ -759,17 +767,28 @@ impl ToolRegistry {
759767 }
760768 }
761769 // Exact deny list
762- for d in & cfg. commands . deny_list {
770+ let mut deny_list = cfg. commands . deny_list . clone ( ) ;
771+ if let Ok ( extra) = std:: env:: var ( "VTAGENT_COMMANDS_DENY_LIST" ) {
772+ deny_list. extend ( extra. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) ) ;
773+ }
774+ for d in & deny_list {
763775 if cmd_text. starts_with ( d) {
764776 return Err ( anyhow ! ( "Command denied by policy: {}" , d) ) ;
765777 }
766778 }
767779
768780 // Allow: if allow_regex/glob present, require one match
769- let mut allow_ok =
770- cfg. commands . allow_regex . is_empty ( ) && cfg. commands . allow_glob . is_empty ( ) ;
781+ let mut allow_regex = cfg. commands . allow_regex . clone ( ) ;
782+ if let Ok ( extra) = std:: env:: var ( "VTAGENT_COMMANDS_ALLOW_REGEX" ) {
783+ allow_regex. extend ( extra. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) ) ;
784+ }
785+ let mut allow_glob = cfg. commands . allow_glob . clone ( ) ;
786+ if let Ok ( extra) = std:: env:: var ( "VTAGENT_COMMANDS_ALLOW_GLOB" ) {
787+ allow_glob. extend ( extra. split ( ',' ) . map ( |s| s. trim ( ) . to_string ( ) ) ) ;
788+ }
789+ let mut allow_ok = allow_regex. is_empty ( ) && allow_glob. is_empty ( ) ;
771790 if !allow_ok {
772- if cfg . commands . allow_regex . iter ( ) . any ( |pat| {
791+ if allow_regex. iter ( ) . any ( |pat| {
773792 Regex :: new ( pat)
774793 . ok ( )
775794 . map ( |re| re. is_match ( & cmd_text) )
@@ -778,7 +797,7 @@ impl ToolRegistry {
778797 allow_ok = true ;
779798 }
780799 if !allow_ok
781- && cfg . commands . allow_glob . iter ( ) . any ( |pat| {
800+ && allow_glob. iter ( ) . any ( |pat| {
782801 let re = format ! ( "^{}$" , regex:: escape( pat) . replace( r"\*" , ".*" ) ) ;
783802 Regex :: new ( & re)
784803 . ok ( )
@@ -791,12 +810,12 @@ impl ToolRegistry {
791810 }
792811 if !allow_ok {
793812 // Fall back to exact allow_list if provided
794- if ! cfg. commands . allow_list . is_empty ( ) {
795- allow_ok = cfg
796- . commands
797- . allow_list
798- . iter ( )
799- . any ( |p| cmd_text. starts_with ( p) ) ;
813+ let mut allow_list = cfg. commands . allow_list . clone ( ) ;
814+ if let Ok ( extra ) = std :: env :: var ( "VTAGENT_COMMANDS_ALLOW_LIST" ) {
815+ allow_list . extend ( extra . split ( ',' ) . map ( |s| s . trim ( ) . to_string ( ) ) ) ;
816+ }
817+ if !allow_list . is_empty ( ) {
818+ allow_ok = allow_list . iter ( ) . any ( |p| cmd_text. starts_with ( p) ) ;
800819 }
801820 }
802821 if !allow_ok {
0 commit comments