fix(telegram): treat exec exit code errors as internal
Command exit codes (like grep returning 1 for no matches) should not be forwarded to users. The model sees these errors in its context and can decide how to proceed - surfacing them clutters the chat with technical messages that aren't actionable by users. Add "exited with code", "exit code", and "aborted" to the list of recoverable/internal error patterns that are suppressed from user output. Before: "⚠️ 🛠️ Exec: grep ... failed: Command exited with code 1" After: (error stays internal, model continues normally) Fixes #3765 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
da71eaebd2
commit
e5547294f3
@ -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: [],
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user