@@ -110,7 +110,13 @@ func (t *batchPatchTool) Schema() any {
110110 }
111111}
112112
113- func (t * batchPatchTool ) Call (argsJSON string ) (string , error ) {
113+ func (t * batchPatchTool ) Call (argsJSON string ) (result string , err error ) {
114+ defer func () {
115+ if r := recover (); r != nil {
116+ err = fmt .Errorf ("batch_patch: panic: %v" , r )
117+ result = `{"error":"internal tool error"}`
118+ }
119+ }()
114120 var args batchPatchArgs
115121 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
116122 return jsonError ("invalid arguments: " + err .Error ())
@@ -282,7 +288,13 @@ func (t *parallelShellTool) Schema() any {
282288 }
283289}
284290
285- func (t * parallelShellTool ) Call (argsJSON string ) (string , error ) {
291+ func (t * parallelShellTool ) Call (argsJSON string ) (result string , err error ) {
292+ defer func () {
293+ if r := recover (); r != nil {
294+ err = fmt .Errorf ("parallel_shell: panic: %v" , r )
295+ result = `{"error":"internal tool error"}`
296+ }
297+ }()
286298 var args parallelShellArgs
287299 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
288300 return jsonError ("invalid arguments: " + err .Error ())
@@ -332,10 +344,14 @@ func (t *parallelShellTool) Call(argsJSON string) (string, error) {
332344 shCmd .Stdout = & stdout
333345 shCmd .Stderr = & stderr
334346
335- // Kill on timeout via goroutine
347+ // Kill on timeout via goroutine, with mutex to avoid Process race
348+ var procMu sync.Mutex
336349 done := make (chan error , 1 )
337350 go func () {
338- done <- shCmd .Run ()
351+ err := shCmd .Run ()
352+ procMu .Lock ()
353+ done <- err
354+ procMu .Unlock ()
339355 }()
340356
341357 select {
@@ -352,9 +368,11 @@ func (t *parallelShellTool) Call(argsJSON string) (string, error) {
352368 }
353369 }
354370 case <- time .After (time .Duration (timeout ) * time .Second ):
371+ procMu .Lock ()
355372 if shCmd .Process != nil {
356373 shCmd .Process .Kill ()
357374 }
375+ procMu .Unlock ()
358376 entry .Error = fmt .Sprintf ("timeout after %ds" , timeout )
359377 entry .DurationMs = time .Since (start ).Milliseconds ()
360378 }
@@ -439,7 +457,13 @@ func (t *httpBatchTool) Schema() any {
439457 }
440458}
441459
442- func (t * httpBatchTool ) Call (argsJSON string ) (string , error ) {
460+ func (t * httpBatchTool ) Call (argsJSON string ) (result string , err error ) {
461+ defer func () {
462+ if r := recover (); r != nil {
463+ err = fmt .Errorf ("http_batch: panic: %v" , r )
464+ result = `{"error":"internal tool error"}`
465+ }
466+ }()
443467 var args httpBatchArgs
444468 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
445469 return jsonError ("invalid arguments: " + err .Error ())
@@ -552,7 +576,13 @@ func (t *mathEvalTool) Schema() any {
552576 }
553577}
554578
555- func (t * mathEvalTool ) Call (argsJSON string ) (string , error ) {
579+ func (t * mathEvalTool ) Call (argsJSON string ) (result string , err error ) {
580+ defer func () {
581+ if r := recover (); r != nil {
582+ err = fmt .Errorf ("math_eval: panic: %v" , r )
583+ result = `{"error":"internal tool error"}`
584+ }
585+ }()
556586 var args mathEvalArgs
557587 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
558588 return jsonError ("invalid arguments: " + err .Error ())
@@ -561,11 +591,11 @@ func (t *mathEvalTool) Call(argsJSON string) (string, error) {
561591 return jsonError ("expression is required" )
562592 }
563593
564- result , err := evalMath (args .Expression )
594+ res , err := evalMath (args .Expression )
565595 if err != nil {
566596 return jsonResult (mathEvalResult {Expression : args .Expression , Error : err .Error ()})
567597 }
568- return jsonResult (mathEvalResult {Expression : args .Expression , Result : result })
598+ return jsonResult (mathEvalResult {Expression : args .Expression , Result : res })
569599}
570600
571601func evalMath (expr string ) (float64 , error ) {
@@ -671,7 +701,13 @@ func (t *diffTool) Schema() any {
671701 }
672702}
673703
674- func (t * diffTool ) Call (argsJSON string ) (string , error ) {
704+ func (t * diffTool ) Call (argsJSON string ) (result string , err error ) {
705+ defer func () {
706+ if r := recover (); r != nil {
707+ err = fmt .Errorf ("diff: panic: %v" , r )
708+ result = `{"error":"internal tool error"}`
709+ }
710+ }()
675711 var args diffArgs
676712 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
677713 return jsonError ("invalid arguments: " + err .Error ())
@@ -1138,7 +1174,13 @@ func (t *jsonQueryTool) Schema() any {
11381174 }
11391175}
11401176
1141- func (t * jsonQueryTool ) Call (argsJSON string ) (string , error ) {
1177+ func (t * jsonQueryTool ) Call (argsJSON string ) (result string , err error ) {
1178+ defer func () {
1179+ if r := recover (); r != nil {
1180+ err = fmt .Errorf ("json_query: panic: %v" , r )
1181+ result = `{"error":"internal tool error"}`
1182+ }
1183+ }()
11421184 var args jsonQueryArgs
11431185 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
11441186 return jsonError ("invalid arguments: " + err .Error ())
@@ -1281,7 +1323,13 @@ func (t *treeTool) Schema() any {
12811323 }
12821324}
12831325
1284- func (t * treeTool ) Call (argsJSON string ) (string , error ) {
1326+ func (t * treeTool ) Call (argsJSON string ) (result string , err error ) {
1327+ defer func () {
1328+ if r := recover (); r != nil {
1329+ err = fmt .Errorf ("tree: panic: %v" , r )
1330+ result = `{"error":"internal tool error"}`
1331+ }
1332+ }()
12851333 var args treeArgs
12861334 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
12871335 return jsonError ("invalid arguments: " + err .Error ())
@@ -1546,7 +1594,13 @@ func (t *sortTool) Schema() any {
15461594 }
15471595}
15481596
1549- func (t * sortTool ) Call (argsJSON string ) (string , error ) {
1597+ func (t * sortTool ) Call (argsJSON string ) (result string , err error ) {
1598+ defer func () {
1599+ if r := recover (); r != nil {
1600+ err = fmt .Errorf ("sort: panic: %v" , r )
1601+ result = `{"error":"internal tool error"}`
1602+ }
1603+ }()
15501604 var args sortArgs
15511605 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
15521606 return jsonError ("invalid arguments: " + err .Error ())
@@ -1609,8 +1663,15 @@ func (t *sortTool) Call(argsJSON string) (string, error) {
16091663 a , b = strings .ToLower (a ), strings .ToLower (b )
16101664 }
16111665 if args .Numeric {
1612- ai , _ := strconv .ParseFloat (strings .Fields (a )[0 ], 64 )
1613- bi , _ := strconv .ParseFloat (strings .Fields (b )[0 ], 64 )
1666+ var ai , bi float64
1667+ fa := strings .Fields (a )
1668+ fb := strings .Fields (b )
1669+ if len (fa ) > 0 {
1670+ ai , _ = strconv .ParseFloat (fa [0 ], 64 )
1671+ }
1672+ if len (fb ) > 0 {
1673+ bi , _ = strconv .ParseFloat (fb [0 ], 64 )
1674+ }
16141675 if desc {
16151676 return ai > bi
16161677 }
@@ -1774,10 +1835,6 @@ func (t *headTailTool) readHead(f *os.File, path string, n int) headTailFileResu
17741835 lines = append (lines , scanner .Text ())
17751836 }
17761837 }
1777- // Continue counting total
1778- for scanner .Scan () {
1779- total ++
1780- }
17811838 return headTailFileResult {Path : path , Lines : lines , Count : len (lines ), Total : total }
17821839}
17831840
@@ -1842,7 +1899,13 @@ func (t *base64Tool) Schema() any {
18421899 }
18431900}
18441901
1845- func (t * base64Tool ) Call (argsJSON string ) (string , error ) {
1902+ func (t * base64Tool ) Call (argsJSON string ) (result string , err error ) {
1903+ defer func () {
1904+ if r := recover (); r != nil {
1905+ err = fmt .Errorf ("base64: panic: %v" , r )
1906+ result = `{"error":"internal tool error"}`
1907+ }
1908+ }()
18461909 var args base64Args
18471910 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
18481911 return jsonError ("invalid arguments: " + err .Error ())
@@ -1939,7 +2002,13 @@ func (t *trTool) Schema() any {
19392002 }
19402003}
19412004
1942- func (t * trTool ) Call (argsJSON string ) (string , error ) {
2005+ func (t * trTool ) Call (argsJSON string ) (result string , err error ) {
2006+ defer func () {
2007+ if r := recover (); r != nil {
2008+ err = fmt .Errorf ("tr: panic: %v" , r )
2009+ result = `{"error":"internal tool error"}`
2010+ }
2011+ }()
19432012 var args trArgs
19442013 if err := json .Unmarshal ([]byte (argsJSON ), & args ); err != nil {
19452014 return jsonError ("invalid arguments: " + err .Error ())
0 commit comments