@@ -33,6 +33,9 @@ const READONLY_COMMANDS: &[&str] = &["ls", "cat", "echo", "pwd", "which", "head"
33
33
#[ derive( Debug , Clone , Deserialize ) ]
34
34
pub struct ExecuteBash {
35
35
pub command : String ,
36
+ /// Optional summary explaining what the command does
37
+ #[ serde( default ) ]
38
+ pub summary : Option < String > ,
36
39
}
37
40
38
41
impl ExecuteBash {
@@ -114,13 +117,29 @@ impl ExecuteBash {
114
117
queue ! ( updates, style:: Print ( "\n " ) , ) ?;
115
118
}
116
119
117
- Ok ( queue ! (
120
+ queue ! (
118
121
updates,
119
122
style:: SetForegroundColor ( Color :: Green ) ,
120
123
style:: Print ( & self . command) ,
121
- style:: Print ( "\n \n " ) ,
124
+ style:: Print ( "\n " ) ,
122
125
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 ( ( ) )
124
143
}
125
144
126
145
pub async fn validate ( & mut self , _ctx : & Context ) -> Result < ( ) > {
@@ -317,6 +336,59 @@ mod tests {
317
336
}
318
337
}
319
338
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
+
320
392
#[ test]
321
393
fn test_requires_acceptance_for_readonly_commands ( ) {
322
394
let cmds = & [
0 commit comments