Files
oh-my-pi/packages/coding-agent/test/bash-failure-result.test.ts
T
can1357 4356298182 fix(coding-agent/tools): handled non-zero bash exits as error results
- Tagged non-zero bash command completions as error results, capturing `exitCode` and keeping exit notices in returned text.
- Updated the shell renderer to hide duplicate exit notices from output while surfacing failed command status in the footer.
- Added tests for non-zero versus zero-exit bash results and footer rendering of failed commands.
2026-05-30 16:31:48 +02:00

60 lines
2.1 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import type { ToolSession } from "../src/tools";
import { BashTool } from "../src/tools/bash";
function makeSession(): ToolSession {
return {
cwd: "/tmp",
hasUI: false,
skills: [],
getSessionFile: () => null,
settings: {
get(key: string) {
if (key === "async.enabled") return false;
if (key === "bash.autoBackground.enabled") return false;
if (key === "bash.autoBackground.thresholdMs") return 60_000;
if (key === "bashInterceptor.enabled") return false;
if (key === "bash.stripTrailingHeadTail") return false;
if (key === "astGrep.enabled") return false;
if (key === "astEdit.enabled") return false;
if (key === "search.enabled") return false;
if (key === "find.enabled") return false;
return undefined;
},
getBashInterceptorRules() {
return [];
},
},
getClientBridge: () => undefined,
} as unknown as ToolSession;
}
describe("BashTool non-zero exit", () => {
it("resolves with an error result carrying execution details instead of throwing", async () => {
const tool = new BashTool(makeSession());
const result = await tool.execute("call-fail", { command: "exit 3" });
// A completed command that failed is a non-throwing error result so the
// renderer keeps the wall time / timeout / exit-code footer.
expect(result.isError).toBe(true);
expect(result.details?.exitCode).toBe(3);
expect(result.details?.timeoutSeconds).toBe(300);
expect(typeof result.details?.wallTimeMs).toBe("number");
// The LLM-facing text still states the exit code verbatim.
const text = result.content.find(c => c.type === "text")?.text ?? "";
expect(text).toContain("Command exited with code 3");
});
it("returns a success result with no exit-code detail for a zero exit", async () => {
const tool = new BashTool(makeSession());
const result = await tool.execute("call-ok", { command: "printf hi" });
expect(result.isError).toBeUndefined();
expect(result.details?.exitCode).toBeUndefined();
const text = result.content.find(c => c.type === "text")?.text ?? "";
expect(text).toContain("hi");
expect(text).not.toContain("Command exited with code");
});
});