fix(ai): omit tool_choice without tools closes #8607

This commit is contained in:
Vegard Stikbakke
2026-08-25 12:26:06 +02:00
parent 240eb29c41
commit fe37e9f9b5
3 changed files with 29 additions and 1 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed OpenAI-compatible Chat Completions requests sending `tool_choice` without tools, which gateways can reject during compaction ([#8607](https://github.com/earendil-works/pi/issues/8607)).
## [0.84.3] - 2026-08-24
### Breaking Changes
+1 -1
View File
@@ -835,7 +835,7 @@ function buildParams(
applyAnthropicCacheControl(messages, params.tools, cacheControl);
}
if (options?.toolChoice) {
if (options?.toolChoice && params.tools?.length) {
params.tool_choice = options.toolChoice;
}
@@ -150,6 +150,30 @@ describe("openai-completions tool_choice", () => {
expect(params.tools?.length ?? 0).toBeGreaterThan(0);
});
it("omits toolChoice when no tools are provided", async () => {
const { compat: _compat, ...baseModel } = getModel("openai", "gpt-4o-mini")!;
const model = { ...baseModel, api: "openai-completions" } as const;
let payload: unknown;
await streamSimple(
model,
{
messages: [{ role: "user", content: "Summarize the conversation", timestamp: Date.now() }],
},
{
apiKey: "test",
toolChoice: "none",
onPayload: (params: unknown) => {
payload = params;
},
},
).result();
const params = (payload ?? mockState.lastParams) as { tool_choice?: string; tools?: unknown[] };
expect(params).not.toHaveProperty("tool_choice");
expect(params).not.toHaveProperty("tools");
});
it("omits strict when compat disables strict mode", async () => {
const { compat: _compat, ...baseModel } = getModel("openai", "gpt-4o-mini")!;
const model = {