From 283570de4da2c4d12f02c069fe1417579f0841b1 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 10 Mar 2026 20:23:03 +0000 Subject: [PATCH] fix: normalize stale openai completions transport --- .../model.provider-normalization.ts | 26 +++++++++- src/agents/pi-embedded-runner/model.test.ts | 48 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/agents/pi-embedded-runner/model.provider-normalization.ts b/src/agents/pi-embedded-runner/model.provider-normalization.ts index ecf1a25e7d3..82dabff7c1b 100644 --- a/src/agents/pi-embedded-runner/model.provider-normalization.ts +++ b/src/agents/pi-embedded-runner/model.provider-normalization.ts @@ -54,9 +54,33 @@ function normalizeOpenAICodexTransport(params: { } as Model; } +function normalizeOpenAITransport(params: { provider: string; model: Model }): Model { + if (normalizeProviderId(params.provider) !== "openai") { + return params.model; + } + + const useResponsesTransport = + params.model.api === "openai-completions" && + (!params.model.baseUrl || isOpenAIApiBaseUrl(params.model.baseUrl)); + + if (!useResponsesTransport) { + return params.model; + } + + return { + ...params.model, + api: "openai-responses", + } as Model; +} + export function normalizeResolvedProviderModel(params: { provider: string; model: Model; }): Model { - return normalizeModelCompat(normalizeOpenAICodexTransport(params)); + const normalizedOpenAI = normalizeOpenAITransport(params); + const normalizedCodex = normalizeOpenAICodexTransport({ + provider: params.provider, + model: normalizedOpenAI, + }); + return normalizeModelCompat(normalizedCodex); } diff --git a/src/agents/pi-embedded-runner/model.test.ts b/src/agents/pi-embedded-runner/model.test.ts index e67fb2c2898..60b34684866 100644 --- a/src/agents/pi-embedded-runner/model.test.ts +++ b/src/agents/pi-embedded-runner/model.test.ts @@ -518,6 +518,54 @@ describe("resolveModel", () => { }); }); + it("normalizes stale native openai gpt-5.4 completions transport to responses", () => { + mockDiscoveredModel({ + provider: "openai", + modelId: "gpt-5.4", + templateModel: buildForwardCompatTemplate({ + id: "gpt-5.4", + name: "GPT-5.4", + provider: "openai", + api: "openai-completions", + baseUrl: "https://api.openai.com/v1", + }), + }); + + const result = resolveModel("openai", "gpt-5.4", "/tmp/agent"); + + expect(result.error).toBeUndefined(); + expect(result.model).toMatchObject({ + provider: "openai", + id: "gpt-5.4", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + }); + }); + + it("keeps proxied openai completions transport untouched", () => { + mockDiscoveredModel({ + provider: "openai", + modelId: "gpt-5.4", + templateModel: buildForwardCompatTemplate({ + id: "gpt-5.4", + name: "GPT-5.4", + provider: "openai", + api: "openai-completions", + baseUrl: "https://proxy.example.com/v1", + }), + }); + + const result = resolveModel("openai", "gpt-5.4", "/tmp/agent"); + + expect(result.error).toBeUndefined(); + expect(result.model).toMatchObject({ + provider: "openai", + id: "gpt-5.4", + api: "openai-completions", + baseUrl: "https://proxy.example.com/v1", + }); + }); + it("builds an anthropic forward-compat fallback for claude-opus-4-6", () => { mockDiscoveredModel({ provider: "anthropic",