@@ -33,6 +33,9 @@ const READONLY_COMMANDS: &[&str] = &["ls", "cat", "echo", "pwd", "which", "head"
3333#[ derive( Debug , Clone , Deserialize ) ]
3434pub struct ExecuteBash {
3535 pub command : String ,
36+ /// Optional summary explaining what the command does
37+ #[ serde( default ) ]
38+ pub summary : Option < String > ,
3639}
3740
3841impl ExecuteBash {
@@ -114,13 +117,29 @@ impl ExecuteBash {
114117 queue ! ( updates, style:: Print ( "\n " ) , ) ?;
115118 }
116119
117- Ok ( queue ! (
120+ queue ! (
118121 updates,
119122 style:: SetForegroundColor ( Color :: Green ) ,
120123 style:: Print ( & self . command) ,
121- style:: Print ( "\n \n " ) ,
124+ style:: Print ( "\n " ) ,
122125 style:: ResetColor
123- ) ?)
126+ ) ?;
127+
128+ // Add the summary if available
129+ if let Some ( summary) = & self . summary {
130+ queue ! (
131+ updates,
132+ style:: SetForegroundColor ( Color :: Blue ) ,
133+ style:: Print ( "\n Purpose: " ) ,
134+ style:: ResetColor ,
135+ style:: Print ( summary) ,
136+ style:: Print ( "\n " ) ,
137+ ) ?;
138+ }
139+
140+ queue ! ( updates, style:: Print ( "\n " ) ) ?;
141+
142+ Ok ( ( ) )
124143 }
125144
126145 pub async fn validate ( & mut self , _ctx : & Context ) -> Result < ( ) > {
@@ -317,6 +336,59 @@ mod tests {
317336 }
318337 }
319338
339+ #[ test]
340+ fn test_deserialize_with_summary ( ) {
341+ let json = r#"{"command": "ls -la", "summary": "List all files with details"}"# ;
342+ let tool = serde_json:: from_str :: < ExecuteBash > ( json) . unwrap ( ) ;
343+ assert_eq ! ( tool. command, "ls -la" ) ;
344+ assert_eq ! ( tool. summary, Some ( "List all files with details" . to_string( ) ) ) ;
345+ }
346+
347+ #[ test]
348+ fn test_deserialize_without_summary ( ) {
349+ let json = r#"{"command": "ls -la"}"# ;
350+ let tool = serde_json:: from_str :: < ExecuteBash > ( json) . unwrap ( ) ;
351+ assert_eq ! ( tool. command, "ls -la" ) ;
352+ assert_eq ! ( tool. summary, None ) ;
353+ }
354+
355+ #[ test]
356+ fn test_queue_description_with_summary ( ) {
357+ let mut buffer = Vec :: new ( ) ;
358+
359+ let tool = ExecuteBash {
360+ command : "ls -la" . to_string ( ) ,
361+ summary : Some ( "List all files in the current directory with details" . to_string ( ) ) ,
362+ } ;
363+
364+ tool. queue_description ( & mut buffer) . unwrap ( ) ;
365+
366+ // Convert to string and print for debugging
367+ let output = String :: from_utf8_lossy ( & buffer) . to_string ( ) ;
368+ println ! ( "Debug output: {:?}" , output) ;
369+
370+ // Check for command and summary text, ignoring ANSI color codes
371+ assert ! ( output. contains( "ls -la" ) ) ;
372+ assert ! ( output. contains( "Purpose:" ) ) ;
373+ assert ! ( output. contains( "List all files in the current directory with details" ) ) ;
374+ }
375+
376+ #[ test]
377+ fn test_queue_description_without_summary ( ) {
378+ let mut buffer = Vec :: new ( ) ;
379+
380+ let tool = ExecuteBash {
381+ command : "ls -la" . to_string ( ) ,
382+ summary : None ,
383+ } ;
384+
385+ tool. queue_description ( & mut buffer) . unwrap ( ) ;
386+
387+ let output = String :: from_utf8 ( buffer) . unwrap ( ) ;
388+ assert ! ( output. contains( "ls -la" ) ) ;
389+ assert ! ( !output. contains( "Purpose:" ) ) ;
390+ }
391+
320392 #[ test]
321393 fn test_requires_acceptance_for_readonly_commands ( ) {
322394 let cmds = & [
0 commit comments