From 734f53fb374048d0bc67cdd6e67845d47d27d8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E6=99=BA=E8=B6=850668000959?= Date: Wed, 3 Jun 2026 17:37:33 +0800 Subject: [PATCH] fix(tools): handle json.Marshal errors in exec tool responses Replace 7 instances of ignored json.Marshal errors with proper error handling. Previously, if marshaling an ExecResponse failed, a nil byte slice would be silently converted to an empty string in the LLM response. Now each site returns ErrorResult with the marshal error message. --- pkg/tools/shell.go | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index 5c2b03f4f..018a77ac9 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -671,7 +671,10 @@ func (t *ExecTool) runBackground(ctx context.Context, command, cwd string, ptyEn SessionID: sessionID, Status: "running", } - data, _ := json.Marshal(resp) + data, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(data), ForUser: fmt.Sprintf("Session %s started", sessionID), @@ -684,7 +687,10 @@ func (t *ExecTool) executeList() *ToolResult { resp := ExecResponse{ Sessions: sessions, } - data, _ := json.Marshal(resp) + data, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(data), ForUser: fmt.Sprintf("%d active sessions", len(sessions)), @@ -711,7 +717,10 @@ func (t *ExecTool) executePoll(args map[string]any) *ToolResult { Status: session.GetStatus(), ExitCode: session.GetExitCode(), } - data, _ := json.Marshal(resp) + data, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(data), IsError: false, @@ -739,7 +748,10 @@ func (t *ExecTool) executeRead(args map[string]any) *ToolResult { Output: output, Status: session.GetStatus(), } - data, _ := json.Marshal(resp) + data, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(data), IsError: false, @@ -769,7 +781,7 @@ func (t *ExecTool) executeWrite(args map[string]any) *ToolResult { return ErrorResult(fmt.Sprintf("process already exited with code %d", session.GetExitCode())) } - if err := session.Write(data); err != nil { + if err = session.Write(data); err != nil { if errors.Is(err, ErrSessionDone) { return ErrorResult(fmt.Sprintf("process already exited with code %d", session.GetExitCode())) } @@ -780,7 +792,10 @@ func (t *ExecTool) executeWrite(args map[string]any) *ToolResult { SessionID: sessionID, Status: session.GetStatus(), } - respData, _ := json.Marshal(resp) + respData, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(respData), IsError: false, @@ -805,7 +820,7 @@ func (t *ExecTool) executeKill(args map[string]any) *ToolResult { return ErrorResult(fmt.Sprintf("process already exited with code %d", session.GetExitCode())) } - if err := session.Kill(); err != nil { + if err = session.Kill(); err != nil { return ErrorResult(fmt.Sprintf("failed to kill session: %v", err)) } @@ -815,7 +830,10 @@ func (t *ExecTool) executeKill(args map[string]any) *ToolResult { SessionID: sessionID, Status: "done", } - data, _ := json.Marshal(resp) + data, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(data), ForUser: fmt.Sprintf("Session %s killed", sessionID), @@ -1027,7 +1045,7 @@ func (t *ExecTool) executeSendKeys(args map[string]any) *ToolResult { return ErrorResult(fmt.Sprintf("process already exited with code %d", session.GetExitCode())) } - if err := session.Write(data); err != nil { + if err = session.Write(data); err != nil { if errors.Is(err, ErrSessionDone) { return ErrorResult(fmt.Sprintf("process already exited with code %d", session.GetExitCode())) } @@ -1039,7 +1057,10 @@ func (t *ExecTool) executeSendKeys(args map[string]any) *ToolResult { Status: "running", Output: fmt.Sprintf("Sent keys: %v", keys), } - respData, _ := json.Marshal(resp) + respData, err := json.Marshal(resp) + if err != nil { + return ErrorResult(err.Error()) + } return &ToolResult{ ForLLM: string(respData), IsError: false,