import { describe, expect, it } from "vitest" ;
import type { OpenClawConfig } from "../config/types.js" ;
import {
deriveAspectRatioFromSize,
normalizeDurationToClosestMax,
resolveCapabilityModelCandidates,
resolveClosestAspectRatio,
resolveClosestResolution,
resolveClosestSize,
} from "./runtime-shared.js" ;
function parseModelRef(raw?: string) {
const trimmed = raw?.trim();
if (!trimmed) {
return null ;
}
const slash = trimmed.indexOf("/" );
if (slash <= 0 || slash === trimmed.length - 1 ) {
return null ;
}
return {
provider: trimmed.slice(0 , slash),
model: trimmed.slice(slash + 1 ),
};
}
describe("media-generation runtime shared candidates" , () => {
it("appends auth-backed provider defaults after explicit refs by default" , () => {
const cfg = {
agents: {
defaults: {
model: {
primary: "openai/gpt-5.4" ,
},
},
},
} as OpenClawConfig;
const candidates = resolveCapabilityModelCandidates({
cfg,
modelConfig: {
primary: "google/gemini-3.1-flash-image-preview" ,
fallbacks: ["fal/fal-ai/flux/dev" ],
},
parseModelRef,
listProviders: () => [
{
id: "google" ,
defaultModel: "gemini-3.1-flash-image-preview" ,
isConfigured: () => true ,
},
{
id: "openai" ,
defaultModel: "gpt-image-1" ,
isConfigured: () => true ,
},
{
id: "minimax" ,
defaultModel: "image-01" ,
isConfigured: () => true ,
},
],
});
expect(candidates).toEqual([
{ provider: "google" , model: "gemini-3.1-flash-image-preview" },
{ provider: "fal" , model: "fal-ai/flux/dev" },
{ provider: "openai" , model: "gpt-image-1" },
{ provider: "minimax" , model: "image-01" },
]);
});
it("auto-detects auth-backed provider defaults when no explicit media model is configured" , () => {
const candidates = resolveCapabilityModelCandidates({
cfg: {} as OpenClawConfig,
modelConfig: undefined,
parseModelRef,
listProviders: () => [
{
id: "openai" ,
defaultModel: "gpt-image-1" ,
isConfigured: () => true ,
},
{
id: "fal" ,
defaultModel: "fal-ai/flux/dev" ,
isConfigured: () => true ,
},
],
});
expect(candidates).toEqual([
{ provider: "openai" , model: "gpt-image-1" },
{ provider: "fal" , model: "fal-ai/flux/dev" },
]);
});
it("disables implicit provider expansion when mediaGenerationAutoProviderFallback=false" , () => {
const candidates = resolveCapabilityModelCandidates({
cfg: {
agents: {
defaults: {
mediaGenerationAutoProviderFallback: false ,
},
},
} as OpenClawConfig,
modelConfig: {
primary: "google/gemini-3.1-flash-image-preview" ,
},
parseModelRef,
listProviders: () => [
{
id: "openai" ,
defaultModel: "gpt-image-1" ,
isConfigured: () => true ,
},
],
});
expect(candidates).toEqual([{ provider: "google" , model: "gemini-3.1-flash-image-preview" }]);
});
it("treats an explicit model override as exact-only" , () => {
const candidates = resolveCapabilityModelCandidates({
cfg: {
agents: {
defaults: {
mediaGenerationAutoProviderFallback: false ,
},
},
} as OpenClawConfig,
modelConfig: {
primary: "google/gemini-3.1-flash-image-preview" ,
fallbacks: ["fal/fal-ai/flux/dev" ],
},
modelOverride: "openai/gpt-image-2" ,
parseModelRef,
listProviders: () => [
{
id: "google" ,
defaultModel: "gemini-3.1-flash-image-preview" ,
isConfigured: () => true ,
},
],
});
expect(candidates).toEqual([{ provider: "openai" , model: "gpt-image-2" }]);
});
});
describe("media-generation runtime shared normalization" , () => {
it("derives reduced aspect ratios from size strings" , () => {
expect(deriveAspectRatioFromSize("1280x720" )).toBe("16:9" );
expect(deriveAspectRatioFromSize("1024x1536" )).toBe("2:3" );
});
it("maps unsupported sizes to the closest supported size" , () => {
expect(
resolveClosestSize({
requestedSize: "1792x1024" ,
supportedSizes: ["1024x1024" , "1024x1536" , "1536x1024" ],
}),
).toBe("1536x1024" );
});
it("maps unsupported aspect ratios to the closest supported aspect ratio" , () => {
expect(
resolveClosestAspectRatio({
requestedAspectRatio: "17:10" ,
supportedAspectRatios: ["1:1" , "4:3" , "16:9" ],
}),
).toBe("16:9" );
});
it("maps unsupported resolutions to the closest supported resolution" , () => {
expect(
resolveClosestResolution({
requestedResolution: "2K" ,
supportedResolutions: ["1K" , "4K" ],
}),
).toBe("1K" );
});
it("clamps durations to the closest supported max" , () => {
expect(normalizeDurationToClosestMax(12 , 8 )).toBe(8 );
expect(normalizeDurationToClosestMax(6 , 8 )).toBe(6 );
});
});
Messung V0.5 in Prozent C=93 H=97 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland