44
55import oslex
66
7+ from cecli .helpers import responses
78from cecli .helpers .hashline import strip_hashline
89from cecli .run_cmd import run_cmd_subprocess
910from cecli .tools .utils .base_tool import BaseTool
@@ -83,6 +84,29 @@ def _find_search_tool(self):
8384 else :
8485 return None , None
8586
87+ @classmethod
88+ def _coerce_searches (cls , searches ) -> list [dict ]:
89+ """Normalize ``searches`` for UI display (local models often double-encode)."""
90+ if isinstance (searches , str ):
91+ parsed = responses .try_parse_json_value (searches )
92+ if isinstance (parsed , list ):
93+ searches = parsed
94+ elif isinstance (parsed , dict ):
95+ searches = [parsed ]
96+ else :
97+ return []
98+ if not isinstance (searches , list ):
99+ return []
100+ out : list [dict ] = []
101+ for item in searches :
102+ if isinstance (item , dict ):
103+ out .append (item )
104+ elif isinstance (item , str ):
105+ parsed = responses .try_parse_json_value (item )
106+ if isinstance (parsed , dict ):
107+ out .append (parsed )
108+ return out
109+
86110 @classmethod
87111 def execute (
88112 cls ,
@@ -98,6 +122,10 @@ def execute(
98122 # Handle legacy single-search call if necessary, or just error
99123 return "Error: 'searches' parameter must be an array."
100124
125+ searches = cls ._coerce_searches (searches )
126+ if not searches :
127+ return "Error: 'searches' parameter must be a non-empty array of search objects."
128+
101129 repo = coder .repo
102130 if not repo :
103131 coder .io .tool_error ("Not in a git repository." )
@@ -236,16 +264,15 @@ def format_output(cls, coder, mcp_server, tool_response):
236264 """Format output for Grep tool."""
237265 color_start , color_end = color_markers (coder )
238266
239- try :
240- params = json .loads (tool_response .function .arguments )
241- except json .JSONDecodeError :
242- coder .io .tool_error ("Invalid Tool JSON" )
267+ params = responses .parse_tool_arguments (tool_response .function .arguments or "" )
268+ if "@error" in params :
269+ coder .io .tool_error (f"Invalid Tool JSON: { params ['@error' ]} " )
243270 return
244271
245272 tool_header (coder = coder , mcp_server = mcp_server , tool_response = tool_response )
246273
247274 # Output each search operation with the requested format
248- searches = params .get ("searches" , [])
275+ searches = cls . _coerce_searches ( params .get ("searches" , []) )
249276 if searches :
250277 coder .io .tool_output ("" )
251278 for i , search_op in enumerate (searches ):
0 commit comments