mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe image generation runtime surface
This commit is contained in:
@@ -1,131 +1,6 @@
|
||||
import {
|
||||
buildNoCapabilityModelConfiguredMessage,
|
||||
resolveCapabilityModelCandidates,
|
||||
throwCapabilityGenerationFailure,
|
||||
} from "openclaw/plugin-sdk/media-generation-runtime-shared";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
describeFailoverError,
|
||||
getImageGenerationProvider,
|
||||
isFailoverError,
|
||||
listImageGenerationProviders,
|
||||
parseImageGenerationModelRef,
|
||||
type AuthProfileStore,
|
||||
type FallbackAttempt,
|
||||
type GeneratedImageAsset,
|
||||
type ImageGenerationResolution,
|
||||
type ImageGenerationResult,
|
||||
type ImageGenerationSourceImage,
|
||||
type OpenClawConfig,
|
||||
} from "../api.js";
|
||||
|
||||
const log = createSubsystemLogger("image-generation");
|
||||
|
||||
export type GenerateImageParams = {
|
||||
cfg: OpenClawConfig;
|
||||
prompt: string;
|
||||
agentDir?: string;
|
||||
authStore?: AuthProfileStore;
|
||||
modelOverride?: string;
|
||||
count?: number;
|
||||
size?: string;
|
||||
aspectRatio?: string;
|
||||
resolution?: ImageGenerationResolution;
|
||||
inputImages?: ImageGenerationSourceImage[];
|
||||
};
|
||||
|
||||
export type GenerateImageRuntimeResult = {
|
||||
images: GeneratedImageAsset[];
|
||||
provider: string;
|
||||
model: string;
|
||||
attempts: FallbackAttempt[];
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
function buildNoImageGenerationModelConfiguredMessage(cfg: OpenClawConfig): string {
|
||||
return buildNoCapabilityModelConfiguredMessage({
|
||||
capabilityLabel: "image-generation",
|
||||
modelConfigKey: "imageGenerationModel",
|
||||
providers: listImageGenerationProviders(cfg),
|
||||
fallbackSampleRef: "google/gemini-3-pro-image-preview",
|
||||
});
|
||||
}
|
||||
|
||||
export function listRuntimeImageGenerationProviders(params?: { config?: OpenClawConfig }) {
|
||||
return listImageGenerationProviders(params?.config);
|
||||
}
|
||||
|
||||
export async function generateImage(
|
||||
params: GenerateImageParams,
|
||||
): Promise<GenerateImageRuntimeResult> {
|
||||
const candidates = resolveCapabilityModelCandidates({
|
||||
cfg: params.cfg,
|
||||
modelConfig: params.cfg.agents?.defaults?.imageGenerationModel,
|
||||
modelOverride: params.modelOverride,
|
||||
parseModelRef: parseImageGenerationModelRef,
|
||||
});
|
||||
if (candidates.length === 0) {
|
||||
throw new Error(buildNoImageGenerationModelConfiguredMessage(params.cfg));
|
||||
}
|
||||
|
||||
const attempts: FallbackAttempt[] = [];
|
||||
let lastError: unknown;
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const provider = getImageGenerationProvider(candidate.provider, params.cfg);
|
||||
if (!provider) {
|
||||
const error = `No image-generation provider registered for ${candidate.provider}`;
|
||||
attempts.push({
|
||||
provider: candidate.provider,
|
||||
model: candidate.model,
|
||||
error,
|
||||
});
|
||||
lastError = new Error(error);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const result: ImageGenerationResult = await provider.generateImage({
|
||||
provider: candidate.provider,
|
||||
model: candidate.model,
|
||||
prompt: params.prompt,
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
authStore: params.authStore,
|
||||
count: params.count,
|
||||
size: params.size,
|
||||
aspectRatio: params.aspectRatio,
|
||||
resolution: params.resolution,
|
||||
inputImages: params.inputImages,
|
||||
});
|
||||
if (!Array.isArray(result.images) || result.images.length === 0) {
|
||||
throw new Error("Image generation provider returned no images.");
|
||||
}
|
||||
return {
|
||||
images: result.images,
|
||||
provider: candidate.provider,
|
||||
model: result.model ?? candidate.model,
|
||||
attempts,
|
||||
metadata: result.metadata,
|
||||
};
|
||||
} catch (err) {
|
||||
lastError = err;
|
||||
const described = isFailoverError(err) ? describeFailoverError(err) : undefined;
|
||||
attempts.push({
|
||||
provider: candidate.provider,
|
||||
model: candidate.model,
|
||||
error: described?.message ?? (err instanceof Error ? err.message : String(err)),
|
||||
reason: described?.reason,
|
||||
status: described?.status,
|
||||
code: described?.code,
|
||||
});
|
||||
log.debug(`image-generation candidate failed: ${candidate.provider}/${candidate.model}`);
|
||||
}
|
||||
}
|
||||
|
||||
throwCapabilityGenerationFailure({
|
||||
capabilityLabel: "image generation",
|
||||
attempts,
|
||||
lastError,
|
||||
});
|
||||
}
|
||||
export {
|
||||
generateImage,
|
||||
listRuntimeImageGenerationProviders,
|
||||
type GenerateImageParams,
|
||||
type GenerateImageRuntimeResult,
|
||||
} from "openclaw/plugin-sdk/image-generation-runtime";
|
||||
|
||||
@@ -580,6 +580,10 @@
|
||||
"types": "./dist/plugin-sdk/image-generation.d.ts",
|
||||
"default": "./dist/plugin-sdk/image-generation.js"
|
||||
},
|
||||
"./plugin-sdk/image-generation-runtime": {
|
||||
"types": "./dist/plugin-sdk/image-generation-runtime.d.ts",
|
||||
"default": "./dist/plugin-sdk/image-generation-runtime.js"
|
||||
},
|
||||
"./plugin-sdk/image-generation-core": {
|
||||
"types": "./dist/plugin-sdk/image-generation-core.d.ts",
|
||||
"default": "./dist/plugin-sdk/image-generation-core.js"
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
"googlechat-runtime-shared",
|
||||
"media-generation-runtime-shared",
|
||||
"image-generation",
|
||||
"image-generation-runtime",
|
||||
"image-generation-core",
|
||||
"music-generation",
|
||||
"music-generation-core",
|
||||
|
||||
6
src/plugin-sdk/image-generation-runtime.ts
Normal file
6
src/plugin-sdk/image-generation-runtime.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export {
|
||||
generateImage,
|
||||
listRuntimeImageGenerationProviders,
|
||||
type GenerateImageParams,
|
||||
type GenerateImageRuntimeResult,
|
||||
} from "../image-generation/runtime.js";
|
||||
Reference in New Issue
Block a user