@@ -122,7 +122,7 @@ impl Drop for PendingSessionRegistration {
122122/// Owns an internal event loop that dispatches events to the per-callback
123123/// handlers installed on the session config.
124124///
125- /// Protocol methods (`send`, `get_messages `, `abort`, etc.) automatically
125+ /// Protocol methods (`send`, `get_events `, `abort`, etc.) automatically
126126/// inject the session ID into RPC params.
127127///
128128/// Call [`destroy`](Self::destroy) for graceful cleanup (RPC + local). If dropped
@@ -788,45 +788,27 @@ impl Client {
788788 if let Some ( transforms) = config. system_message_transform . clone ( ) {
789789 inject_transform_sections ( & mut config, transforms. as_ref ( ) ) ;
790790 }
791- let wire = config. to_wire ( session_id. clone ( ) ) ;
791+ let ( wire, mut runtime ) = config. into_wire ( session_id. clone ( ) ) ? ;
792792
793793 let permission_handler = crate :: permission:: resolve_handler (
794- config . permission_handler . take ( ) ,
795- config . permission_policy . take ( ) ,
794+ runtime . permission_handler . take ( ) ,
795+ runtime . permission_policy . take ( ) ,
796796 ) ;
797- let elicitation_handler = config. elicitation_handler . take ( ) ;
798- let user_input_handler = config. user_input_handler . take ( ) ;
799- let exit_plan_mode_handler = config. exit_plan_mode_handler . take ( ) ;
800- let auto_mode_switch_handler = config. auto_mode_switch_handler . take ( ) ;
801- let mut tool_map: HashMap < String , Arc < dyn crate :: tool:: ToolHandler > > = HashMap :: new ( ) ;
802- if let Some ( tools) = config. tools . as_mut ( ) {
803- for tool in tools. iter_mut ( ) {
804- if let Some ( handler) = tool. handler . take ( ) {
805- if tool_map. contains_key ( & tool. name ) {
806- return Err ( Error :: InvalidConfig ( format ! (
807- "duplicate tool handler registered for name {:?}" ,
808- tool. name
809- ) ) ) ;
810- }
811- tool_map. insert ( tool. name . clone ( ) , handler) ;
812- }
813- }
814- }
815797 let handlers = SessionHandlers {
816798 permission : permission_handler,
817- elicitation : elicitation_handler,
818- user_input : user_input_handler,
819- exit_plan_mode : exit_plan_mode_handler,
820- auto_mode_switch : auto_mode_switch_handler,
821- tools : Arc :: new ( tool_map ) ,
799+ elicitation : runtime . elicitation_handler . take ( ) ,
800+ user_input : runtime . user_input_handler . take ( ) ,
801+ exit_plan_mode : runtime . exit_plan_mode_handler . take ( ) ,
802+ auto_mode_switch : runtime . auto_mode_switch_handler . take ( ) ,
803+ tools : Arc :: new ( std :: mem :: take ( & mut runtime . tool_handlers ) ) ,
822804 } ;
823- let hooks = config . hooks_handler . take ( ) ;
824- let transforms = config . system_message_transform . take ( ) ;
825- let tools_count = config . tools . as_ref ( ) . map_or ( 0 , Vec :: len) ;
826- let commands_count = config . commands . as_ref ( ) . map_or ( 0 , Vec :: len) ;
805+ let hooks = runtime . hooks_handler . take ( ) ;
806+ let transforms = runtime . system_message_transform . take ( ) ;
807+ let tools_count = wire . tools . as_ref ( ) . map_or ( 0 , Vec :: len) ;
808+ let commands_count = runtime . commands . as_ref ( ) . map_or ( 0 , Vec :: len) ;
827809 let has_hooks = hooks. is_some ( ) ;
828- let command_handlers = build_command_handler_map ( config . commands . as_deref ( ) ) ;
829- let session_fs_provider = config . session_fs_provider . take ( ) ;
810+ let command_handlers = build_command_handler_map ( runtime . commands . as_deref ( ) ) ;
811+ let session_fs_provider = runtime . session_fs_provider . take ( ) ;
830812 if self . inner . session_fs_configured && session_fs_provider. is_none ( ) {
831813 return Err ( Error :: Session ( SessionError :: SessionFsProviderRequired ) ) ;
832814 }
@@ -943,45 +925,27 @@ impl Client {
943925 if let Some ( transforms) = config. system_message_transform . clone ( ) {
944926 inject_transform_sections_resume ( & mut config, transforms. as_ref ( ) ) ;
945927 }
946- let wire = config. to_wire ( ) ;
928+ let ( wire, mut runtime ) = config. into_wire ( ) ? ;
947929
948930 let permission_handler = crate :: permission:: resolve_handler (
949- config . permission_handler . take ( ) ,
950- config . permission_policy . take ( ) ,
931+ runtime . permission_handler . take ( ) ,
932+ runtime . permission_policy . take ( ) ,
951933 ) ;
952- let elicitation_handler = config. elicitation_handler . take ( ) ;
953- let user_input_handler = config. user_input_handler . take ( ) ;
954- let exit_plan_mode_handler = config. exit_plan_mode_handler . take ( ) ;
955- let auto_mode_switch_handler = config. auto_mode_switch_handler . take ( ) ;
956- let mut tool_map: HashMap < String , Arc < dyn crate :: tool:: ToolHandler > > = HashMap :: new ( ) ;
957- if let Some ( tools) = config. tools . as_mut ( ) {
958- for tool in tools. iter_mut ( ) {
959- if let Some ( handler) = tool. handler . take ( ) {
960- if tool_map. contains_key ( & tool. name ) {
961- return Err ( Error :: InvalidConfig ( format ! (
962- "duplicate tool handler registered for name {:?}" ,
963- tool. name
964- ) ) ) ;
965- }
966- tool_map. insert ( tool. name . clone ( ) , handler) ;
967- }
968- }
969- }
970934 let handlers = SessionHandlers {
971935 permission : permission_handler,
972- elicitation : elicitation_handler,
973- user_input : user_input_handler,
974- exit_plan_mode : exit_plan_mode_handler,
975- auto_mode_switch : auto_mode_switch_handler,
976- tools : Arc :: new ( tool_map ) ,
936+ elicitation : runtime . elicitation_handler . take ( ) ,
937+ user_input : runtime . user_input_handler . take ( ) ,
938+ exit_plan_mode : runtime . exit_plan_mode_handler . take ( ) ,
939+ auto_mode_switch : runtime . auto_mode_switch_handler . take ( ) ,
940+ tools : Arc :: new ( std :: mem :: take ( & mut runtime . tool_handlers ) ) ,
977941 } ;
978- let hooks = config . hooks_handler . take ( ) ;
979- let transforms = config . system_message_transform . take ( ) ;
980- let tools_count = config . tools . as_ref ( ) . map_or ( 0 , Vec :: len) ;
981- let commands_count = config . commands . as_ref ( ) . map_or ( 0 , Vec :: len) ;
942+ let hooks = runtime . hooks_handler . take ( ) ;
943+ let transforms = runtime . system_message_transform . take ( ) ;
944+ let tools_count = wire . tools . as_ref ( ) . map_or ( 0 , Vec :: len) ;
945+ let commands_count = runtime . commands . as_ref ( ) . map_or ( 0 , Vec :: len) ;
982946 let has_hooks = hooks. is_some ( ) ;
983- let command_handlers = build_command_handler_map ( config . commands . as_deref ( ) ) ;
984- let session_fs_provider = config . session_fs_provider . take ( ) ;
947+ let command_handlers = build_command_handler_map ( runtime . commands . as_deref ( ) ) ;
948+ let session_fs_provider = runtime . session_fs_provider . take ( ) ;
985949 if self . inner . session_fs_configured && session_fs_provider. is_none ( ) {
986950 return Err ( Error :: Session ( SessionError :: SessionFsProviderRequired ) ) ;
987951 }
@@ -1464,12 +1428,12 @@ async fn handle_notification(
14641428 ) ;
14651429 tokio:: spawn (
14661430 async move {
1467- if data . tool_call_id . is_empty ( ) || data . tool_name . is_empty ( ) {
1468- let error_msg = if data . tool_call_id . is_empty ( ) {
1469- "Missing toolCallId"
1470- } else {
1471- "Missing toolName"
1472- } ;
1431+ // `tool_name. is_empty()` would have produced a `None`
1432+ // lookup in `handlers.tools` and short-circuited at the
1433+ // outer guard above, so only the tool_call_id check is
1434+ // reachable here.
1435+ if data . tool_call_id . is_empty ( ) {
1436+ let error_msg = "Missing toolCallId" ;
14731437 let rpc_start = Instant :: now ( ) ;
14741438 let _ = client
14751439 . call (
0 commit comments