1313
1414from cecli import utils
1515from cecli .change_tracker import ChangeTracker
16- from cecli .helpers import nested
16+ from cecli .helpers import nested , responses
1717from cecli .helpers .background_commands import BackgroundCommandManager
1818from cecli .helpers .conversation import ConversationService , MessageTag
1919from cecli .helpers .similarity import (
@@ -124,7 +124,7 @@ def _get_agent_config(self):
124124 config ["command_timeout" ] = nested .getter (config , "command_timeout" , 30 )
125125 config ["hot_reload" ] = nested .getter (config , "hot_reload" , False )
126126
127- config ["tools_paths" ] = nested .getter (config , "tools_paths" , [])
127+ config ["tools_paths" ] = nested .getter (config , [ "tools_paths" , "tool_paths" ] , [])
128128 config ["tools_includelist" ] = nested .getter (
129129 config , ["tools_includelist" , "tools_whitelist" ], []
130130 )
@@ -246,7 +246,7 @@ async def _execute_local_tool_calls(self, tool_calls_list):
246246 tool_name = tool_call .function .name
247247 result_message = ""
248248 try :
249- if tool_name .lower () in self .write_tools :
249+ if responses . unprefix_tool_name ( tool_name )[ 1 ] .lower () in self .write_tools :
250250 used_write_tool = True
251251
252252 args_string = tool_call .function .arguments .strip ()
@@ -738,8 +738,11 @@ async def process_tool_calls(self, tool_call_response):
738738
739739 if tool_name :
740740 self .last_round_tools .append (tool_name )
741+ content = (
742+ str (self .partial_response_content ) if self .partial_response_content else ""
743+ )
741744 tool_call_str = str (tool_call_copy )
742- tool_vector = create_bigram_vector ((tool_call_str ,))
745+ tool_vector = create_bigram_vector ((tool_call_str , content ))
743746 tool_vector_norm = normalize_vector (tool_vector )
744747 self .tool_call_vectors .append (tool_vector_norm )
745748 if self .last_round_tools :
@@ -753,6 +756,27 @@ async def process_tool_calls(self, tool_call_response):
753756 # Ensure we call base implementation to trigger execution of all tools (native + extracted)
754757 return await super ().process_tool_calls (tool_call_response )
755758
759+ async def _execute_local_tools (self , tool_calls ):
760+ """Execute local tools via ToolRegistry."""
761+ return await self ._execute_local_tool_calls (tool_calls )
762+
763+ async def _execute_mcp_tools (self , server , tool_calls ):
764+ """Execute MCP tools via LiteLLM."""
765+ responses = []
766+ for tool_call in tool_calls :
767+ # Use existing _execute_mcp_tool logic
768+ result = await self ._execute_mcp_tool (
769+ server , tool_call .function .name , json .loads (tool_call .function .arguments )
770+ )
771+ responses .append (
772+ {
773+ "role" : "tool" ,
774+ "tool_call_id" : tool_call .id ,
775+ "content" : result ,
776+ }
777+ )
778+ return responses
779+
756780 def get_active_model (self ):
757781 if self .main_model .agent_model :
758782 return self .main_model .agent_model
@@ -870,14 +894,15 @@ def _get_repetitive_tools(self):
870894 Identifies repetitive tool usage patterns from rounds of tool calls.
871895 """
872896 history_len = len (self .tool_usage_history )
873- if history_len < 5 :
897+ if history_len < 1 :
874898 return set ()
875899
876900 similarity_repetitive_tools = self ._get_repetitive_tools_by_similarity ()
877901
878902 if self .last_round_tools :
879903 last_round_has_write = any (
880- tool .lower () in self .write_tools for tool in self .last_round_tools
904+ responses .unprefix_tool_name (tool )[1 ].lower () in self .write_tools
905+ for tool in self .last_round_tools
881906 )
882907 if last_round_has_write :
883908 # Remove half of the history when a write tool is used
@@ -889,7 +914,8 @@ def _get_repetitive_tools(self):
889914 return {
890915 tool
891916 for tool in similarity_repetitive_tools
892- if tool .lower () in self .read_tools or tool .lower () in self .write_tools
917+ if responses .unprefix_tool_name (tool )[1 ].lower () in self .read_tools
918+ or responses .unprefix_tool_name (tool )[1 ].lower () in self .write_tools
893919 }
894920
895921 def _get_repetitive_tools_by_similarity (self ):
@@ -990,6 +1016,8 @@ def _generate_tool_context(self, repetitive_tools):
9901016 )
9911017
9921018 context_parts .append ("\n \n " )
1019+ repetition_warning = None
1020+
9931021 if repetitive_tools :
9941022 if not self .model_kwargs :
9951023 self .model_kwargs = {
@@ -1019,7 +1047,7 @@ def _generate_tool_context(self, repetitive_tools):
10191047 )
10201048 self .model_kwargs ["frequency_penalty" ] = min (0 , max (freq_penalty - 0.15 , 0 ))
10211049
1022- self .model_kwargs ["temperature" ] = min (self .model_kwargs ["temperature" ], 1 )
1050+ self .model_kwargs ["temperature" ] = max ( 0 , min (self .model_kwargs ["temperature" ], 1 ) )
10231051 # One twentieth of the time, just straight reset the randomness
10241052 if random .random () < 0.05 :
10251053 self .model_kwargs = {}
@@ -1028,11 +1056,11 @@ def _generate_tool_context(self, repetitive_tools):
10281056 self ._last_repetitive_warning_turn = self .turn_count
10291057 self ._last_repetitive_warning_severity += 1
10301058
1031- repetition_warning = f"""
1032- ## Repetition Detected
1033- You have been using the following tools repetitively: { ', ' .join ([f'`{ t } `' for t in repetitive_tools ])} .
1034- Do not repeat the same parameters for these tools in your next turns. Prioritize editing.
1035- """
1059+ repetition_warning = (
1060+ " ## Repetition Detected\n You have used the following tools repetitively:"
1061+ f" { ', ' .join ([f'`{ t } `' for t in repetitive_tools ])} .\n Do not repeat the same"
1062+ " parameters for these tools in your next turns. Prioritize editing.\n "
1063+ )
10361064
10371065 if self ._last_repetitive_warning_severity > 5 :
10381066 self ._last_repetitive_warning_severity = 0
@@ -1079,28 +1107,42 @@ def _generate_tool_context(self, repetitive_tools):
10791107 ]
10801108 )
10811109
1082- repetition_warning += f"""
1083- ## CRITICAL: Execution Loop Detected
1084- You may be stuck in a cycle. To break the exploration loop and continue making progress, please do the following:
1085- 1. **Analyze**: Summarize your findings. Describe how you can stop repeating yourself and make progress.
1086- 2. **Reframe**: To help with creativity, include a 2-sentence story about { animal } { verb } { fruit } in your thoughts.
1087- 3. **Pivot**: Modify your current exploration strategy. Try alternative methods. Prioritize editing.
1088- """
1110+ repetition_warning += (
1111+ "## CRITICAL: Execution Loop Detected\n You may be stuck in a cycle. To break"
1112+ " the exploration loop and continue making progress, please do the"
1113+ " following:\n 1. **Analyze**: Summarize your findings. Describe how you can"
1114+ " stop repeating yourself and make progress.2. **Reframe**: To help with"
1115+ f" creativity, include a 2-sentence story about { animal } { verb } { fruit } in your"
1116+ " thoughts.\n 3. **Pivot**: Modify your current exploration strategy. Try"
1117+ " alternative methods. Prioritize editing.\n "
1118+ )
10891119
1090- context_parts .append (repetition_warning )
1120+ # context_parts.append(repetition_warning)
10911121 else :
10921122 self .model_kwargs = {}
10931123 self ._last_repetitive_warning_severity = min (
10941124 self ._last_repetitive_warning_severity - 1 , 0
10951125 )
10961126
1127+ if repetition_warning :
1128+ ConversationService .get_manager (self ).add_message (
1129+ message_dict = dict (role = "user" , content = repetition_warning ),
1130+ tag = MessageTag .CUR ,
1131+ hash_key = ("repetition" , "agent" ),
1132+ mark_for_delete = 0 ,
1133+ promotion = ConversationService .get_manager (self ).DEFAULT_TAG_PROMOTION_VALUE + 2 ,
1134+ mark_for_demotion = 1 ,
1135+ force = True ,
1136+ )
1137+
10971138 context_parts .append ("</context>" )
10981139 return "\n " .join (context_parts )
10991140
11001141 def _generate_write_context (self ):
11011142 if self .last_round_tools :
11021143 last_round_has_write = any (
1103- tool .lower () in self .write_tools for tool in self .last_round_tools
1144+ responses .unprefix_tool_name (tool )[1 ].lower () in self .write_tools
1145+ for tool in self .last_round_tools
11041146 )
11051147 if last_round_has_write :
11061148 context_parts = [
0 commit comments