@@ -33,6 +33,7 @@ use crate::util::types::Message as AIMessage;
3333use crate :: util:: types:: ToolDefinition ;
3434use crate :: util:: { elapsed_ms_u64, truncate_at_char_boundary} ;
3535use log:: { debug, error, info, trace, warn} ;
36+ use sha2:: { Digest , Sha256 } ;
3637use std:: collections:: { HashMap , HashSet } ;
3738use std:: path:: Path ;
3839use std:: sync:: Arc ;
@@ -112,10 +113,12 @@ impl ExecutionEngine {
112113 return args_str. to_string ( ) ;
113114 }
114115
116+ let args_hash = hex:: encode ( Sha256 :: digest ( args_str. as_bytes ( ) ) ) ;
115117 format ! (
116- "{}..#{}" ,
118+ "{}..#{}:sha256={} " ,
117119 truncate_at_char_boundary( args_str, 64 ) ,
118- args_str. len( )
120+ args_str. len( ) ,
121+ args_hash
119122 )
120123 }
121124
@@ -1961,6 +1964,7 @@ mod tests {
19611964 use crate :: service:: config:: types:: AIConfig ;
19621965 use crate :: service:: config:: types:: AIModelConfig ;
19631966 use serde_json:: json;
1967+ use sha2:: { Digest , Sha256 } ;
19641968
19651969 fn build_model ( id : & str , name : & str , model_name : & str ) -> AIModelConfig {
19661970 AIModelConfig {
@@ -2008,10 +2012,14 @@ mod tests {
20082012 #[ test]
20092013 fn tool_signature_args_summary_truncates_on_utf8_boundary ( ) {
20102014 let args = format ! ( "{}{}" , "a" . repeat( 62 ) , "案" . repeat( 30 ) ) ;
2015+ let args_hash = hex:: encode ( Sha256 :: digest ( args. as_bytes ( ) ) ) ;
20112016
20122017 let summary = ExecutionEngine :: tool_signature_args_summary ( & args) ;
20132018
2014- assert_eq ! ( summary, format!( "{}..#{}" , "a" . repeat( 62 ) , args. len( ) ) ) ;
2019+ assert_eq ! (
2020+ summary,
2021+ format!( "{}..#{}:sha256={}" , "a" . repeat( 62 ) , args. len( ) , args_hash)
2022+ ) ;
20152023 }
20162024
20172025 #[ test]
@@ -2023,6 +2031,19 @@ mod tests {
20232031 assert_eq ! ( summary, args) ;
20242032 }
20252033
2034+ #[ test]
2035+ fn tool_signature_args_summary_distinguishes_same_prefix_and_length ( ) {
2036+ let first = format ! ( "{}{}" , "x" . repeat( 64 ) , "a" . repeat( 80 ) ) ;
2037+ let second = format ! ( "{}{}" , "x" . repeat( 64 ) , "b" . repeat( 80 ) ) ;
2038+
2039+ let first_summary = ExecutionEngine :: tool_signature_args_summary ( & first) ;
2040+ let second_summary = ExecutionEngine :: tool_signature_args_summary ( & second) ;
2041+
2042+ assert_eq ! ( first. len( ) , second. len( ) ) ;
2043+ assert_ne ! ( first, second) ;
2044+ assert_ne ! ( first_summary, second_summary) ;
2045+ }
2046+
20262047 #[ test]
20272048 fn assistant_has_tool_calls_detects_mixed_tool_message ( ) {
20282049 let message = Message :: assistant_with_tools (
0 commit comments