@@ -815,12 +815,12 @@ impl Agents {
815815 // This "static" way avoids needing to construct a tool instance.
816816 fn default_permission_label ( & self , tool_name : & str ) -> String {
817817 let label = match tool_name {
818- "fs_read" => "trusted" . dark_green ( ) . bold ( ) ,
818+ "fs_read" => "trust working directory" . dark_grey ( ) ,
819819 "fs_write" => "not trusted" . dark_grey ( ) ,
820820 #[ cfg( not( windows) ) ]
821- "execute_bash" => "trust read-only commands " . dark_grey ( ) ,
821+ "execute_bash" => "not trusted " . dark_grey ( ) ,
822822 #[ cfg( windows) ]
823- "execute_cmd" => "trust read-only commands " . dark_grey ( ) ,
823+ "execute_cmd" => "not trusted " . dark_grey ( ) ,
824824 "use_aws" => "trust read-only commands" . dark_grey ( ) ,
825825 "report_issue" => "trusted" . dark_green ( ) . bold ( ) ,
826826 "introspect" => "trusted" . dark_green ( ) . bold ( ) ,
@@ -959,6 +959,7 @@ mod tests {
959959 use serde_json:: json;
960960
961961 use super :: * ;
962+ use crate :: cli:: agent:: hook:: Source ;
962963 const INPUT : & str = r#"
963964 {
964965 "name": "some_agent",
@@ -968,21 +969,21 @@ mod tests {
968969 "fetch": { "command": "fetch3.1", "args": [] },
969970 "git": { "command": "git-mcp", "args": [] }
970971 },
971- "tools": [
972+ "tools": [
972973 "@git"
973974 ],
974975 "toolAliases": {
975976 "@gits/some_tool": "some_tool2"
976977 },
977- "allowedTools": [
978- "fs_read",
978+ "allowedTools": [
979+ "fs_read",
979980 "@fetch",
980981 "@gits/git_status"
981982 ],
982- "resources": [
983+ "resources": [
983984 "file://~/my-genai-prompts/unittest.md"
984985 ],
985- "toolsSettings": {
986+ "toolsSettings": {
986987 "fs_write": { "allowedPaths": ["~/**"] },
987988 "@git/git_status": { "git_user": "$GIT_USER" }
988989 }
@@ -1142,9 +1143,9 @@ mod tests {
11421143
11431144 let label = agents. display_label ( "fs_read" , & ToolOrigin :: Native ) ;
11441145 // With no active agent, it should fall back to default permissions
1145- // fs_read has a default of "trusted "
1146+ // fs_read has a default of "trust working directory "
11461147 assert ! (
1147- label. contains( "trusted " ) ,
1148+ label. contains( "trust working directory " ) ,
11481149 "fs_read should show default trusted permission, instead found: {}" ,
11491150 label
11501151 ) ;
@@ -1173,7 +1174,7 @@ mod tests {
11731174 // Test default permissions for known tools
11741175 let fs_read_label = agents. display_label ( "fs_read" , & ToolOrigin :: Native ) ;
11751176 assert ! (
1176- fs_read_label. contains( "trusted " ) ,
1177+ fs_read_label. contains( "trust working directory " ) ,
11771178 "fs_read should be trusted by default, instead found: {}" ,
11781179 fs_read_label
11791180 ) ;
@@ -1188,8 +1189,8 @@ mod tests {
11881189 let execute_name = if cfg ! ( windows) { "execute_cmd" } else { "execute_bash" } ;
11891190 let execute_bash_label = agents. display_label ( execute_name, & ToolOrigin :: Native ) ;
11901191 assert ! (
1191- execute_bash_label. contains( "read-only " ) ,
1192- "execute_bash should show read-only by default, instead found: {}" ,
1192+ execute_bash_label. contains( "not trusted " ) ,
1193+ "execute_bash should not be trusted by default, instead found: {}" ,
11931194 execute_bash_label
11941195 ) ;
11951196 }
@@ -1353,4 +1354,70 @@ mod tests {
13531354
13541355 assert_eq ! ( agents. get_active( ) . and_then( |a| a. model. as_ref( ) ) , None ) ;
13551356 }
1357+
1358+ #[ test]
1359+ fn test_agent_with_hooks ( ) {
1360+ let agent_json = json ! ( {
1361+ "name" : "test-agent" ,
1362+ "hooks" : {
1363+ "agentSpawn" : [
1364+ {
1365+ "command" : "git status"
1366+ }
1367+ ] ,
1368+ "preToolUse" : [
1369+ {
1370+ "matcher" : "fs_write" ,
1371+ "command" : "validate-tool.sh"
1372+ } ,
1373+ {
1374+ "matcher" : "fs_read" ,
1375+ "command" : "enforce-tdd.sh"
1376+ }
1377+ ] ,
1378+ "postToolUse" : [
1379+ {
1380+ "matcher" : "fs_write" ,
1381+ "command" : "format-python.sh"
1382+ }
1383+ ]
1384+ }
1385+ } ) ;
1386+
1387+ let agent: Agent = serde_json:: from_value ( agent_json) . expect ( "Failed to deserialize agent" ) ;
1388+
1389+ // Verify agent name
1390+ assert_eq ! ( agent. name, "test-agent" ) ;
1391+
1392+ // Verify agentSpawn hook
1393+ assert ! ( agent. hooks. contains_key( & HookTrigger :: AgentSpawn ) ) ;
1394+ let agent_spawn_hooks = & agent. hooks [ & HookTrigger :: AgentSpawn ] ;
1395+ assert_eq ! ( agent_spawn_hooks. len( ) , 1 ) ;
1396+ assert_eq ! ( agent_spawn_hooks[ 0 ] . command, "git status" ) ;
1397+ assert_eq ! ( agent_spawn_hooks[ 0 ] . matcher, None ) ;
1398+
1399+ // Verify preToolUse hooks
1400+ assert ! ( agent. hooks. contains_key( & HookTrigger :: PreToolUse ) ) ;
1401+ let pre_tool_hooks = & agent. hooks [ & HookTrigger :: PreToolUse ] ;
1402+ assert_eq ! ( pre_tool_hooks. len( ) , 2 ) ;
1403+
1404+ assert_eq ! ( pre_tool_hooks[ 0 ] . command, "validate-tool.sh" ) ;
1405+ assert_eq ! ( pre_tool_hooks[ 0 ] . matcher, Some ( "fs_write" . to_string( ) ) ) ;
1406+
1407+ assert_eq ! ( pre_tool_hooks[ 1 ] . command, "enforce-tdd.sh" ) ;
1408+ assert_eq ! ( pre_tool_hooks[ 1 ] . matcher, Some ( "fs_read" . to_string( ) ) ) ;
1409+
1410+ // Verify postToolUse hooks
1411+ assert ! ( agent. hooks. contains_key( & HookTrigger :: PostToolUse ) ) ;
1412+
1413+ // Verify default values are set correctly
1414+ for hooks in agent. hooks . values ( ) {
1415+ for hook in hooks {
1416+ assert_eq ! ( hook. timeout_ms, 30_000 ) ;
1417+ assert_eq ! ( hook. max_output_size, 10_240 ) ;
1418+ assert_eq ! ( hook. cache_ttl_seconds, 0 ) ;
1419+ assert_eq ! ( hook. source, Source :: Agent ) ;
1420+ }
1421+ }
1422+ }
13561423}
0 commit comments