@@ -1213,7 +1213,7 @@ impl Daemon {
12131213 shutdown_rx : & mut mpsc:: Receiver < ( ) > ,
12141214 plugin_manager : crate :: api:: plugins:: SharedPluginManager ,
12151215 ) -> Result < ( ) > {
1216- // Available for future tool filtering by channel policy
1216+ // Voice uses Full profile — tool_policy checked at handler level
12171217 let _ = & tool_policy;
12181218
12191219 let wake_word =
@@ -1539,8 +1539,7 @@ async fn handle_channel_messages<C: Channel + Send + 'static>(
15391539 plugin_manager : crate :: api:: plugins:: SharedPluginManager ,
15401540 telegram_config : Option < crate :: config:: TelegramConfig > ,
15411541) {
1542- // Available for future tool filtering by channel policy
1543- let _ = & tool_policy;
1542+ let exec_tool = Arc :: new ( crate :: tools:: BuiltinExecTool :: default ( ) ) ;
15441543
15451544 tracing:: info!( channel = channel_name, "channel handler started" ) ;
15461545
@@ -1789,13 +1788,25 @@ async fn handle_channel_messages<C: Channel + Send + 'static>(
17891788 }
17901789 }
17911790
1792- // Fetch available tools from Synapse MCP and plugins
1791+ // Fetch available tools from Synapse MCP and plugins, filtered by policy
17931792 let tools = {
17941793 let executor = crate :: tools:: executor:: ToolExecutor :: new (
17951794 Arc :: clone ( & synapse) ,
17961795 plugin_manager. clone ( ) ,
1797- ) ;
1798- executor. list_tools ( ) . await . ok ( )
1796+ )
1797+ . with_exec_tool ( Arc :: clone ( & exec_tool) ) ;
1798+ executor. list_tools ( ) . await . ok ( ) . map ( |tools| {
1799+ let filtered: Vec < _ > = tools
1800+ . into_iter ( )
1801+ . filter ( |t| {
1802+ tool_policy
1803+ . is_allowed ( channel_name, & normalize_tool_name ( & t. function . name ) )
1804+ } )
1805+ . collect ( ) ;
1806+ let names: Vec < & str > = filtered. iter ( ) . map ( |t| t. function . name . as_str ( ) ) . collect ( ) ;
1807+ tracing:: info!( channel = channel_name, tools = ?names, "tools available for LLM" ) ;
1808+ filtered
1809+ } )
17991810 } ;
18001811
18011812 let use_streaming = channel
@@ -1827,7 +1838,8 @@ async fn handle_channel_messages<C: Channel + Send + 'static>(
18271838 let executor = crate :: tools:: executor:: ToolExecutor :: new (
18281839 Arc :: clone ( & synapse) ,
18291840 plugin_manager. clone ( ) ,
1830- ) ;
1841+ )
1842+ . with_exec_tool ( Arc :: clone ( & exec_tool) ) ;
18311843 let mut loop_detector = crate :: tools:: loop_detection:: LoopDetector :: default ( ) ;
18321844
18331845 for _turn in 0 ..10 {
@@ -1941,6 +1953,11 @@ async fn handle_channel_messages<C: Channel + Send + 'static>(
19411953
19421954 let mut should_break = false ;
19431955 for tc in & tool_calls {
1956+ tracing:: info!(
1957+ tool = %tc. function. name,
1958+ args_len = tc. function. arguments. len( ) ,
1959+ "executing tool call"
1960+ ) ;
19441961 let result = executor
19451962 . execute ( & tc. function . name , & tc. function . arguments )
19461963 . await
@@ -2220,9 +2237,11 @@ async fn handle_voice_command(
22202237 } ;
22212238
22222239 // Fetch available tools from Synapse MCP and plugins
2240+ let exec_tool = Arc :: new ( crate :: tools:: BuiltinExecTool :: default ( ) ) ;
22232241 let tools = {
22242242 let executor =
2225- crate :: tools:: executor:: ToolExecutor :: new ( Arc :: clone ( synapse) , plugin_manager. clone ( ) ) ;
2243+ crate :: tools:: executor:: ToolExecutor :: new ( Arc :: clone ( synapse) , plugin_manager. clone ( ) )
2244+ . with_exec_tool ( Arc :: clone ( & exec_tool) ) ;
22262245 executor. list_tools ( ) . await . ok ( )
22272246 } ;
22282247
@@ -2232,7 +2251,8 @@ async fn handle_voice_command(
22322251 ] ;
22332252 let mut final_text = String :: new ( ) ;
22342253 let executor =
2235- crate :: tools:: executor:: ToolExecutor :: new ( Arc :: clone ( synapse) , plugin_manager. clone ( ) ) ;
2254+ crate :: tools:: executor:: ToolExecutor :: new ( Arc :: clone ( synapse) , plugin_manager. clone ( ) )
2255+ . with_exec_tool ( exec_tool) ;
22362256
22372257 for _turn in 0 ..10 {
22382258 let request = synapse_client:: ChatRequest {
@@ -2345,6 +2365,17 @@ fn extract_command(transcript: &str, wake_word: &str) -> String {
23452365 )
23462366}
23472367
2368+ /// Map LLM tool names to policy category names
2369+ fn normalize_tool_name ( name : & str ) -> String {
2370+ match name {
2371+ "Bash" => "shell" . to_string ( ) ,
2372+ "Read" | "Glob" | "Grep" | "WebFetch" | "ListDir" => "read_file" . to_string ( ) ,
2373+ "Write" | "Edit" => "write_file" . to_string ( ) ,
2374+ "WebSearch" => "web_search" . to_string ( ) ,
2375+ other => other. to_string ( ) ,
2376+ }
2377+ }
2378+
23482379#[ cfg( test) ]
23492380mod tests {
23502381 use super :: * ;
@@ -2357,4 +2388,20 @@ mod tests {
23572388 ) ;
23582389 assert_eq ! ( extract_command( "Hey Orin" , "hey orin" ) , "" ) ;
23592390 }
2391+
2392+ #[ test]
2393+ fn test_normalize_tool_name ( ) {
2394+ assert_eq ! ( normalize_tool_name( "Bash" ) , "shell" ) ;
2395+ assert_eq ! ( normalize_tool_name( "Read" ) , "read_file" ) ;
2396+ assert_eq ! ( normalize_tool_name( "Write" ) , "write_file" ) ;
2397+ assert_eq ! ( normalize_tool_name( "Edit" ) , "write_file" ) ;
2398+ assert_eq ! ( normalize_tool_name( "WebSearch" ) , "web_search" ) ;
2399+ assert_eq ! ( normalize_tool_name( "WebFetch" ) , "read_file" ) ;
2400+ assert_eq ! ( normalize_tool_name( "Glob" ) , "read_file" ) ;
2401+ assert_eq ! ( normalize_tool_name( "Grep" ) , "read_file" ) ;
2402+ assert_eq ! ( normalize_tool_name( "ListDir" ) , "read_file" ) ;
2403+ // Unknown tools pass through
2404+ assert_eq ! ( normalize_tool_name( "memory_store" ) , "memory_store" ) ;
2405+ assert_eq ! ( normalize_tool_name( "cron_list" ) , "cron_list" ) ;
2406+ }
23602407}
0 commit comments