Skip to content

Commit a27a25f

Browse files
authored
Merge pull request #1164 from devoxx/fix/run-command-nonzero-exit-error-icon
fix: classify non-zero run_command exit as agent tool error
2 parents e2fd116 + ccdc735 commit a27a25f

3 files changed

Lines changed: 41 additions & 4 deletions

File tree

src/main/java/com/devoxx/genie/service/agent/AgentLoopTracker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private String track(@NotNull ToolExecutionRequest toolRequest, @NotNull ToolInv
157157
* Returns {@code true} when a tool result string represents an error by convention —
158158
* i.e. it starts with the "Error:" prefix used across the built-in tool executors.
159159
*/
160-
static boolean isErrorResult(@Nullable String result) {
160+
public static boolean isErrorResult(@Nullable String result) {
161161
return result != null && result.stripLeading().startsWith("Error:");
162162
}
163163

src/main/java/com/devoxx/genie/service/agent/tool/RunCommandToolExecutor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ private String formatResult(int exitCode, String output) {
189189
if (exitCode == 0) {
190190
return result.isEmpty() ? "(command completed successfully with no output)" : result;
191191
} else {
192-
return "Exit code: " + exitCode + "\n" + result;
192+
// Prefix with "Error:" so AgentLoopTracker.isErrorResult() classifies a non-zero
193+
// exit as TOOL_ERROR (red icon) instead of a green "success" check in the Activity
194+
// panel. The exit code is kept in the message for the LLM's benefit.
195+
return "Error: Command exited with code " + exitCode + "\n" + result;
193196
}
194197
}
195198

src/test/java/com/devoxx/genie/service/agent/tool/RunCommandToolExecutorTest.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.devoxx.genie.service.agent.tool;
22

3+
import com.devoxx.genie.service.agent.AgentLoopTracker;
34
import com.intellij.openapi.project.Project;
45
import com.intellij.openapi.util.SystemInfo;
56
import dev.langchain4j.agent.tool.ToolExecutionRequest;
@@ -142,7 +143,7 @@ void execute_nonZeroExitCode_withOutput_returnsExitCodeAndOutput() {
142143
.build();
143144

144145
String result = executor.execute(request, null);
145-
assertThat(result).contains("Exit code: 2").contains("failing");
146+
assertThat(result).contains("exited with code 2").contains("failing");
146147
}
147148

148149
@Test
@@ -247,7 +248,40 @@ void execute_nonZeroExitCode_returnsExitCode() {
247248
.build();
248249

249250
String result = executor.execute(request, null);
250-
assertThat(result).contains("Exit code: 1");
251+
assertThat(result).contains("exited with code 1");
252+
}
253+
254+
/**
255+
* Reproduces the bug where a command exiting with a non-zero code was rendered
256+
* with the green "success" icon in the agent Activity panel. The icon is decided
257+
* by {@link AgentLoopTracker#isErrorResult(String)}, which only flags strings
258+
* beginning with "Error:". A non-zero exit must therefore produce an
259+
* "Error:"-prefixed result so it is classified as TOOL_ERROR (red icon).
260+
*/
261+
@Test
262+
void execute_nonZeroExitCode_isClassifiedAsError() {
263+
ToolExecutionRequest request = ToolExecutionRequest.builder()
264+
.name("run_command")
265+
.arguments("{\"command\": \"exit 1\"}")
266+
.build();
267+
268+
String result = executor.execute(request, null);
269+
assertThat(AgentLoopTracker.isErrorResult(result))
270+
.as("Non-zero exit code must be classified as an error result")
271+
.isTrue();
272+
}
273+
274+
@Test
275+
void execute_zeroExitCode_isNotClassifiedAsError() {
276+
ToolExecutionRequest request = ToolExecutionRequest.builder()
277+
.name("run_command")
278+
.arguments("{\"command\": \"echo ok\"}")
279+
.build();
280+
281+
String result = executor.execute(request, null);
282+
assertThat(AgentLoopTracker.isErrorResult(result))
283+
.as("Successful command must not be classified as an error result")
284+
.isFalse();
251285
}
252286

253287
@Test

0 commit comments

Comments
 (0)