fix(openai): share responses transport defaults

This commit is contained in:
Vincent Koc
2026-04-14 16:25:30 +01:00
parent 9c42e6424d
commit 60961a7f55
4 changed files with 74 additions and 24 deletions

View File

@@ -28,6 +28,7 @@ import { buildOpenAIReplayPolicy } from "./replay-policy.js";
import {
buildOpenAISyntheticCatalogEntry,
cloneFirstTemplateModel,
defaultOpenAIResponsesExtraParams,
findCatalogTemplate,
isOpenAIApiBaseUrl,
isOpenAICodexBaseUrl,
@@ -336,16 +337,7 @@ export function buildOpenAICodexProviderPlugin(): ProviderPlugin {
return id === OPENAI_CODEX_GPT_54_MODEL_ID || id === OPENAI_CODEX_GPT_54_PRO_MODEL_ID;
},
buildReplayPolicy: buildOpenAIReplayPolicy,
prepareExtraParams: (ctx) => {
const transport = ctx.extraParams?.transport;
if (transport === "auto" || transport === "sse" || transport === "websocket") {
return ctx.extraParams;
}
return {
...ctx.extraParams,
transport: "auto",
};
},
prepareExtraParams: (ctx) => defaultOpenAIResponsesExtraParams(ctx.extraParams),
...OPENAI_RESPONSES_STREAM_HOOKS,
resolveTransportTurnState: (ctx) => resolveOpenAITransportTurnState(ctx),
resolveWebSocketSessionPolicy: (ctx) => resolveOpenAIWebSocketSessionPolicy(ctx),

View File

@@ -353,6 +353,51 @@ describe("buildOpenAIProvider", () => {
expect(result.payload.reasoning).toEqual({ effort: "none" });
});
it("preserves explicit OpenAI responses transport and warmup overrides", () => {
const provider = buildOpenAIProvider();
const explicit = {
transport: "websocket",
openaiWsWarmup: false,
fastMode: true,
};
expect(
provider.prepareExtraParams?.({
provider: "openai",
modelId: "gpt-5.4",
extraParams: explicit,
} as never),
).toBe(explicit);
});
it("defaults Codex responses transport without forcing warmup flags", () => {
const provider = buildOpenAICodexProviderPlugin();
expect(
provider.prepareExtraParams?.({
provider: "openai-codex",
modelId: "gpt-5.4",
extraParams: { effort: "high" },
} as never),
).toEqual({
effort: "high",
transport: "auto",
});
const explicit = {
transport: "sse",
openaiWsWarmup: false,
};
expect(
provider.prepareExtraParams?.({
provider: "openai-codex",
modelId: "gpt-5.4",
extraParams: explicit,
} as never),
).toBe(explicit);
});
it("owns Azure OpenAI reasoning compatibility without forcing OpenAI transport defaults", () => {
const provider = buildOpenAIProvider();
const wrap = provider.wrapStreamFn;

View File

@@ -16,6 +16,7 @@ import { buildOpenAIReplayPolicy } from "./replay-policy.js";
import {
buildOpenAISyntheticCatalogEntry,
cloneFirstTemplateModel,
defaultOpenAIResponsesExtraParams,
findCatalogTemplate,
isOpenAIApiBaseUrl,
matchesExactOrPrefix,
@@ -222,20 +223,8 @@ export function buildOpenAIProvider(): ProviderPlugin {
? { api: "openai-responses", baseUrl }
: undefined,
buildReplayPolicy: buildOpenAIReplayPolicy,
prepareExtraParams: (ctx) => {
const transport = ctx.extraParams?.transport;
const hasSupportedTransport =
transport === "auto" || transport === "sse" || transport === "websocket";
const hasExplicitWarmup = typeof ctx.extraParams?.openaiWsWarmup === "boolean";
if (hasSupportedTransport && hasExplicitWarmup) {
return ctx.extraParams;
}
return {
...ctx.extraParams,
...(hasSupportedTransport ? {} : { transport: "auto" }),
...(hasExplicitWarmup ? {} : { openaiWsWarmup: true }),
};
},
prepareExtraParams: (ctx) =>
defaultOpenAIResponsesExtraParams(ctx.extraParams, { openaiWsWarmup: true }),
...OPENAI_RESPONSES_STREAM_HOOKS,
matchesContextOverflowError: ({ errorMessage }) =>
/content_filter.*(?:prompt|input).*(?:too long|exceed)/i.test(errorMessage),

View File

@@ -50,6 +50,30 @@ export function isOpenAICodexBaseUrl(baseUrl?: string): boolean {
return /^https?:\/\/chatgpt\.com\/backend-api\/?$/i.test(trimmed);
}
function hasSupportedOpenAIResponsesTransport(
transport: unknown,
): transport is "auto" | "sse" | "websocket" {
return transport === "auto" || transport === "sse" || transport === "websocket";
}
export function defaultOpenAIResponsesExtraParams(
extraParams: Record<string, unknown> | undefined,
options?: { openaiWsWarmup?: boolean },
): Record<string, unknown> | undefined {
const hasSupportedTransport = hasSupportedOpenAIResponsesTransport(extraParams?.transport);
const hasExplicitWarmup = typeof extraParams?.openaiWsWarmup === "boolean";
const shouldDefaultWarmup = options?.openaiWsWarmup === true;
if (hasSupportedTransport && (!shouldDefaultWarmup || hasExplicitWarmup)) {
return extraParams;
}
return {
...extraParams,
...(hasSupportedTransport ? {} : { transport: "auto" }),
...(shouldDefaultWarmup && !hasExplicitWarmup ? { openaiWsWarmup: true } : {}),
};
}
export function buildOpenAISyntheticCatalogEntry(
template: ReturnType<typeof findCatalogTemplate>,
entry: {