@@ -227,10 +227,9 @@ impl Agent {
227227 StreamEvent :: ToolUseEnd => {
228228 if let Some ( mut tool) = current_tool. take ( ) {
229229 // Parse the accumulated JSON
230- let tool_input = ToolCall :: normalize_input_to_object (
230+ let tool_input =
231231 serde_json:: from_str :: < serde_json:: Value > ( & current_tool_input)
232- . unwrap_or ( serde_json:: Value :: Null ) ,
233- ) ;
232+ . unwrap_or ( serde_json:: Value :: Null ) ;
234233 tool. input = tool_input. clone ( ) ;
235234 tool. intent = ToolCall :: intent_from_input ( & tool_input) ;
236235
@@ -647,12 +646,37 @@ impl Agent {
647646 // Execute tools and add results
648647 let mut tool_results_dirty = false ;
649648 for tc in tool_calls {
650- self . validate_tool_allowed ( & tc. name ) ?;
651-
652649 let message_id = assistant_message_id
653650 . clone ( )
654651 . unwrap_or_else ( || self . session . id . clone ( ) ) ;
655652
653+ if let Some ( error_msg) = tc. validation_error ( ) {
654+ logging:: warn ( & error_msg) ;
655+ Bus :: global ( ) . publish ( BusEvent :: ToolUpdated ( ToolEvent {
656+ session_id : self . session . id . clone ( ) ,
657+ message_id : message_id. clone ( ) ,
658+ tool_call_id : tc. id . clone ( ) ,
659+ tool_name : tc. name . clone ( ) ,
660+ status : ToolStatus :: Error ,
661+ title : None ,
662+ } ) ) ;
663+ if print_output {
664+ println ! ( "\n → {}" , error_msg) ;
665+ }
666+ self . add_message (
667+ Role :: User ,
668+ vec ! [ ContentBlock :: ToolResult {
669+ tool_use_id: tc. id,
670+ content: error_msg,
671+ is_error: Some ( true ) ,
672+ } ] ,
673+ ) ;
674+ tool_results_dirty = true ;
675+ continue ;
676+ }
677+
678+ self . validate_tool_allowed ( & tc. name ) ?;
679+
656680 let is_native_tool = JCODE_NATIVE_TOOLS . contains ( & tc. name . as_str ( ) ) ;
657681
658682 // Check if SDK already executed this tool
0 commit comments