refactor: dedupe openai base url helper

This commit is contained in:
Peter Steinberger
2026-04-06 19:45:12 +01:00
parent 413a5ef75a
commit 60fb7a318e
4 changed files with 63 additions and 14 deletions

View File

@@ -7,7 +7,7 @@ import {
resolveProviderHttpRequestConfig,
} from "openclaw/plugin-sdk/provider-http";
import { OPENAI_DEFAULT_IMAGE_MODEL as DEFAULT_OPENAI_IMAGE_MODEL } from "./default-models.js";
import { toOpenAIDataUrl } from "./shared.js";
import { resolveConfiguredOpenAIBaseUrl, toOpenAIDataUrl } from "./shared.js";
const DEFAULT_OPENAI_IMAGE_BASE_URL = "https://api.openai.com/v1";
const DEFAULT_OUTPUT_MIME = "image/png";
@@ -22,11 +22,6 @@ type OpenAIImageApiResponse = {
}>;
};
function resolveOpenAIBaseUrl(cfg: Parameters<typeof resolveApiKeyForProvider>[0]["cfg"]): string {
const direct = cfg?.models?.providers?.openai?.baseUrl?.trim();
return direct || DEFAULT_OPENAI_IMAGE_BASE_URL;
}
export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider {
return {
id: "openai",
@@ -71,7 +66,7 @@ export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider {
}
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
resolveProviderHttpRequestConfig({
baseUrl: resolveOpenAIBaseUrl(req.cfg),
baseUrl: resolveConfiguredOpenAIBaseUrl(req.cfg),
defaultBaseUrl: DEFAULT_OPENAI_IMAGE_BASE_URL,
defaultHeaders: {
Authorization: `Bearer ${auth.apiKey}`,

View File

@@ -1,3 +1,4 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { findCatalogTemplate } from "openclaw/plugin-sdk/provider-catalog-shared";
import {
cloneFirstTemplateModel,
@@ -10,6 +11,10 @@ export function toOpenAIDataUrl(buffer: Buffer, mimeType: string): string {
return `data:${mimeType};base64,${buffer.toString("base64")}`;
}
export function resolveConfiguredOpenAIBaseUrl(cfg: OpenClawConfig | undefined): string {
return cfg?.models?.providers?.openai?.baseUrl?.trim() || OPENAI_API_BASE_URL;
}
export function isOpenAIApiBaseUrl(baseUrl?: string): boolean {
const trimmed = baseUrl?.trim();
if (!trimmed) {

View File

@@ -151,6 +151,60 @@ describe("openai video generation provider", () => {
);
});
it("honors configured baseUrl for video requests", async () => {
postJsonRequestMock.mockResolvedValue({
response: {
json: async () => ({
id: "vid_local",
model: "sora-2",
status: "queued",
}),
},
release: vi.fn(async () => {}),
});
fetchWithTimeoutMock
.mockResolvedValueOnce({
json: async () => ({
id: "vid_local",
model: "sora-2",
status: "completed",
}),
})
.mockResolvedValueOnce({
headers: new Headers({ "content-type": "video/mp4" }),
arrayBuffer: async () => Buffer.from("mp4-bytes"),
});
const provider = buildOpenAIVideoGenerationProvider();
await provider.generateVideo({
provider: "openai",
model: "sora-2",
prompt: "Render via local relay",
cfg: {
models: {
providers: {
openai: {
baseUrl: "http://127.0.0.1:44080/v1",
models: [],
},
},
},
},
});
expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith(
expect.objectContaining({
baseUrl: "http://127.0.0.1:44080/v1",
}),
);
expect(postJsonRequestMock).toHaveBeenCalledWith(
expect.objectContaining({
url: "http://127.0.0.1:44080/v1/videos",
allowPrivateNetwork: false,
}),
);
});
it("uses multipart input_reference for video-to-video uploads", async () => {
fetchWithTimeoutMock
.mockResolvedValueOnce({

View File

@@ -11,7 +11,7 @@ import type {
VideoGenerationProvider,
VideoGenerationRequest,
} from "openclaw/plugin-sdk/video-generation";
import { toOpenAIDataUrl } from "./shared.js";
import { resolveConfiguredOpenAIBaseUrl, toOpenAIDataUrl } from "./shared.js";
const DEFAULT_OPENAI_VIDEO_BASE_URL = "https://api.openai.com/v1";
const DEFAULT_OPENAI_VIDEO_MODEL = "sora-2";
@@ -36,11 +36,6 @@ type OpenAIVideoResponse = {
} | null;
};
function resolveOpenAIVideoBaseUrl(req: VideoGenerationRequest): string {
const direct = req.cfg?.models?.providers?.openai?.baseUrl?.trim();
return direct || DEFAULT_OPENAI_VIDEO_BASE_URL;
}
function toBlobBytes(buffer: Buffer): ArrayBuffer {
const arrayBuffer = new ArrayBuffer(buffer.byteLength);
new Uint8Array(arrayBuffer).set(buffer);
@@ -227,7 +222,7 @@ export function buildOpenAIVideoGenerationProvider(): VideoGenerationProvider {
const fetchFn = fetch;
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
resolveProviderHttpRequestConfig({
baseUrl: resolveOpenAIVideoBaseUrl(req),
baseUrl: resolveConfiguredOpenAIBaseUrl(req.cfg),
defaultBaseUrl: DEFAULT_OPENAI_VIDEO_BASE_URL,
allowPrivateNetwork: false,
defaultHeaders: {