diff --git a/src/agents/pi-embedded-runner/run/payloads.test.ts b/src/agents/pi-embedded-runner/run/payloads.test.ts index 7a38cc8d2..735f69319 100644 --- a/src/agents/pi-embedded-runner/run/payloads.test.ts +++ b/src/agents/pi-embedded-runner/run/payloads.test.ts @@ -148,7 +148,7 @@ describe("buildEmbeddedRunPayloads", () => { expect(payloads[0]?.text).toBe("All good"); }); - it("adds tool error fallback when the assistant only invoked tools", () => { + it("suppresses exit code errors as internal (model sees them in context)", () => { const payloads = buildEmbeddedRunPayloads({ assistantTexts: [], toolMetas: [], @@ -171,10 +171,9 @@ describe("buildEmbeddedRunPayloads", () => { toolResultFormat: "plain", }); - expect(payloads).toHaveLength(1); - expect(payloads[0]?.isError).toBe(true); - expect(payloads[0]?.text).toContain("Exec"); - expect(payloads[0]?.text).toContain("code 1"); + // Exit code errors should be treated as internal - the model sees them in context + // and can decide how to proceed. Users shouldn't see "grep returned exit code 1" etc. + expect(payloads).toHaveLength(0); }); it("suppresses recoverable tool errors containing 'required'", () => { @@ -226,6 +225,22 @@ describe("buildEmbeddedRunPayloads", () => { expect(payloads).toHaveLength(0); }); + it("suppresses aborted command errors", () => { + const payloads = buildEmbeddedRunPayloads({ + assistantTexts: [], + toolMetas: [], + lastAssistant: undefined, + lastToolError: { toolName: "exec", error: "Command aborted by signal SIGTERM" }, + sessionKey: "session:telegram", + inlineToolResultsAllowed: false, + verboseLevel: "off", + reasoningLevel: "off", + toolResultFormat: "plain", + }); + + expect(payloads).toHaveLength(0); + }); + it("shows non-recoverable tool errors to the user", () => { const payloads = buildEmbeddedRunPayloads({ assistantTexts: [], diff --git a/src/agents/pi-embedded-runner/run/payloads.ts b/src/agents/pi-embedded-runner/run/payloads.ts index 567314f9f..857ed43eb 100644 --- a/src/agents/pi-embedded-runner/run/payloads.ts +++ b/src/agents/pi-embedded-runner/run/payloads.ts @@ -189,7 +189,12 @@ export function buildEmbeddedRunPayloads(params: { errorLower.includes("must be") || errorLower.includes("must have") || errorLower.includes("needs") || - errorLower.includes("requires"); + errorLower.includes("requires") || + // Treat command exit codes as internal - the model sees them and can decide how to proceed. + // Exit code 1 from grep/find/etc. just means "no matches", not a real error. + errorLower.includes("exited with code") || + errorLower.includes("exit code") || + errorLower.includes("aborted"); // Show tool errors only when: // 1. There's no user-facing reply AND the error is not recoverable