





















@@ -824,6 +824,93 @@ describe("openai codex provider", () => {
824824});
825825});
826826827+it("restores [text,image] input on stale gpt-5.5 rows that omit the input field", () => {
828+// Regression: persisted/configured catalog rows can omit the `input` field
829+// for openai-codex models. When that row wins the catalog merge,
830+// `modelSupportsInput(entry, "image")` returns false and the gateway routes
831+// inbound images down the claim-check offload path (`media://inbound/<id>`)
832+// instead of inlining them. Mirror of the Anthropic precedent set by
833+// upstream #83756.
834+const provider = buildOpenAICodexProviderPlugin();
835+836+const model = provider.normalizeResolvedModel?.({
837+provider: "openai-codex",
838+modelId: "gpt-5.5",
839+model: {
840+id: "gpt-5.5",
841+name: "gpt-5.5",
842+provider: "openai-codex",
843+api: "openai-codex-responses",
844+baseUrl: "https://chatgpt.com/backend-api/codex",
845+reasoning: true,
846+// No `input` field at all — the stale persisted/configured row shape.
847+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
848+contextWindow: 1_050_000,
849+contextTokens: 272_000,
850+maxTokens: 128_000,
851+},
852+} as never);
853+854+expect(model?.input).toEqual(["text", "image"]);
855+});
856+857+it("preserves [text,image] input on rows that already declare image capability", () => {
858+const provider = buildOpenAICodexProviderPlugin();
859+860+const model = provider.normalizeResolvedModel?.({
861+provider: "openai-codex",
862+modelId: "gpt-5.5",
863+model: {
864+id: "gpt-5.5",
865+name: "gpt-5.5",
866+provider: "openai-codex",
867+api: "openai-codex-responses",
868+baseUrl: "https://chatgpt.com/backend-api/codex",
869+reasoning: true,
870+input: ["text", "image"],
871+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
872+contextWindow: 1_050_000,
873+contextTokens: 272_000,
874+maxTokens: 128_000,
875+},
876+} as never);
877+878+// Existing image capability untouched; transport is already canonical so
879+// normalizeResolvedModel may return undefined (no-op).
880+if (model) {
881+expect(model.input).toEqual(["text", "image"]);
882+}
883+});
884+885+it("leaves codex-suffix and legacy model rows text-only (not vision-capable)", () => {
886+const provider = buildOpenAICodexProviderPlugin();
887+888+const model = provider.normalizeResolvedModel?.({
889+provider: "openai-codex",
890+modelId: "gpt-5.3-codex",
891+model: {
892+id: "gpt-5.3-codex",
893+name: "gpt-5.3-codex",
894+provider: "openai-codex",
895+api: "openai-codex-responses",
896+baseUrl: "https://chatgpt.com/backend-api/codex",
897+reasoning: true,
898+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
899+contextWindow: 400_000,
900+contextTokens: 272_000,
901+maxTokens: 128_000,
902+},
903+} as never);
904+905+// No image capability should be added — gpt-5.X-codex models are
906+// Codex CLI / agent-mode only and not in the documented vision list.
907+// normalizeResolvedModel may return undefined (no transport change) or a
908+// model with the existing input array; either way `image` must not appear.
909+if (model?.input) {
910+expect(model.input).not.toContain("image");
911+}
912+});
913+827914it("normalizes transport metadata for stale /backend-api/v1 codex routes", () => {
828915const provider = buildOpenAICodexProviderPlugin();
829916此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。