fix(openai): preserve image routing before catalog load (#105518)

* fix(openai): handle image providers without model catalogs

* test(openai): use exported config contract

* test(openai): model provider overlays before catalog load
This commit is contained in:
Vincent Koc
2026-07-12 18:27:57 +02:00
committed by GitHub
parent 8573f9e016
commit 007f714dca
2 changed files with 31 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
// Openai tests cover image generation provider plugin behavior.
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { afterEach, describe, expect, it, vi } from "vitest";
import { buildOpenAIImageGenerationProvider } from "./image-generation-provider.js";
@@ -728,6 +729,35 @@ describe("openai image generation provider", () => {
expect(result.metadata).toBeUndefined();
});
it("falls back to the provider baseUrl when the model catalog is omitted", async () => {
mockGeneratedPngResponse();
const provider = buildOpenAIImageGenerationProvider();
// Plugin-scoped runtime snapshots can carry a built-in provider overlay
// before its model catalog is present.
const cfg = {
models: {
providers: {
openai: {
baseUrl: "https://openai-compatible.example.com/v1",
},
},
},
} as unknown as OpenClawConfig;
const result = await provider.generateImage({
provider: "openai",
model: "gpt-image-2",
prompt: "Create an image through a provider overlay",
cfg,
});
expect(httpConfigCall().baseUrl).toBe("https://openai-compatible.example.com/v1");
expect(jsonRequestCall().url).toBe(
"https://openai-compatible.example.com/v1/images/generations",
);
expect(result.images).toHaveLength(1);
});
it("forwards output and OpenAI-only options on direct generations", async () => {
mockGeneratedPngResponse();

View File

@@ -268,7 +268,7 @@ function resolveNativeOpenAIImageSizesForModel(model: string): readonly string[]
function resolveConfiguredOpenAIImageBaseUrl(cfg: OpenClawConfig | undefined, model: string) {
const modelId = model.trim().replace(/^openai\//u, "");
const modelBaseUrl = cfg?.models?.providers?.openai?.models
.find((candidate) => candidate.id.trim().replace(/^openai\//u, "") === modelId)
?.find((candidate) => candidate.id.trim().replace(/^openai\//u, "") === modelId)
?.baseUrl?.trim();
return modelBaseUrl || resolveConfiguredOpenAIBaseUrl(cfg);
}