mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 09:01:14 +00:00
fix(ai): filter empty error assistant messages in transformMessages
When 429/500 errors occur during tool execution, empty assistant messages with stopReason='error' get persisted. These break the tool_use -> tool_result chain for Claude/Gemini APIs. Added centralized filtering in transformMessages to skip assistant messages with empty content and no tool calls. Provider-level filters remain for defense-in-depth.
This commit is contained in:
parent
d2f9ab110c
commit
fbb74bb29e
11 changed files with 125 additions and 8 deletions
|
|
@ -105,4 +105,36 @@ describe("SettingsManager", () => {
|
|||
expect(savedSettings.defaultThinkingLevel).toBe("high");
|
||||
});
|
||||
});
|
||||
|
||||
describe("shellCommandPrefix", () => {
|
||||
it("should load shellCommandPrefix from settings", () => {
|
||||
const settingsPath = join(agentDir, "settings.json");
|
||||
writeFileSync(settingsPath, JSON.stringify({ shellCommandPrefix: "shopt -s expand_aliases" }));
|
||||
|
||||
const manager = SettingsManager.create(projectDir, agentDir);
|
||||
|
||||
expect(manager.getShellCommandPrefix()).toBe("shopt -s expand_aliases");
|
||||
});
|
||||
|
||||
it("should return undefined when shellCommandPrefix is not set", () => {
|
||||
const settingsPath = join(agentDir, "settings.json");
|
||||
writeFileSync(settingsPath, JSON.stringify({ theme: "dark" }));
|
||||
|
||||
const manager = SettingsManager.create(projectDir, agentDir);
|
||||
|
||||
expect(manager.getShellCommandPrefix()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should preserve shellCommandPrefix when saving unrelated settings", () => {
|
||||
const settingsPath = join(agentDir, "settings.json");
|
||||
writeFileSync(settingsPath, JSON.stringify({ shellCommandPrefix: "shopt -s expand_aliases" }));
|
||||
|
||||
const manager = SettingsManager.create(projectDir, agentDir);
|
||||
manager.setTheme("light");
|
||||
|
||||
const savedSettings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
||||
expect(savedSettings.shellCommandPrefix).toBe("shopt -s expand_aliases");
|
||||
expect(savedSettings.theme).toBe("light");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -299,6 +299,31 @@ describe("Coding Agent Tools", () => {
|
|||
|
||||
await expect(bashWithBadShell.execute("test-call-12", { command: "echo test" })).rejects.toThrow(/ENOENT/);
|
||||
});
|
||||
|
||||
it("should prepend command prefix when configured", async () => {
|
||||
const bashWithPrefix = createBashTool(testDir, {
|
||||
commandPrefix: "export TEST_VAR=hello",
|
||||
});
|
||||
|
||||
const result = await bashWithPrefix.execute("test-prefix-1", { command: "echo $TEST_VAR" });
|
||||
expect(getTextOutput(result).trim()).toBe("hello");
|
||||
});
|
||||
|
||||
it("should include output from both prefix and command", async () => {
|
||||
const bashWithPrefix = createBashTool(testDir, {
|
||||
commandPrefix: "echo prefix-output",
|
||||
});
|
||||
|
||||
const result = await bashWithPrefix.execute("test-prefix-2", { command: "echo command-output" });
|
||||
expect(getTextOutput(result).trim()).toBe("prefix-output\ncommand-output");
|
||||
});
|
||||
|
||||
it("should work without command prefix", async () => {
|
||||
const bashWithoutPrefix = createBashTool(testDir, {});
|
||||
|
||||
const result = await bashWithoutPrefix.execute("test-prefix-3", { command: "echo no-prefix" });
|
||||
expect(getTextOutput(result).trim()).toBe("no-prefix");
|
||||
});
|
||||
});
|
||||
|
||||
describe("grep tool", () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue