diff --git a/web/src/lib/canvas/canvas-project-generation.ts b/web/src/lib/canvas/canvas-project-generation.ts index 20d5dd2dd..899eb138a 100644 --- a/web/src/lib/canvas/canvas-project-generation.ts +++ b/web/src/lib/canvas/canvas-project-generation.ts @@ -42,12 +42,13 @@ export async function runBackendCanvasGenerationTask({ metadata?: Record; onTaskCreated?: (task: GenerationTask) => void; }) { + const normalizedReferenceImages = mode === "image" ? limitCanvasImageReferences(config, referenceImages) : referenceImages; return runBackendGenerationTask({ projectId, mode, prompt, config, - referenceImages, + referenceImages: normalizedReferenceImages, referenceVideos, referenceAudios, mask, @@ -57,6 +58,14 @@ export async function runBackendCanvasGenerationTask({ }); } +// Canvas references can include a scene frame plus multiple character turnarounds. Keep +// the earliest connected scene image when a provider accepts fewer images than the graph. +export function limitCanvasImageReferences(config: AiConfig, referenceImages: ReferenceImage[]) { + const maxImages = modelCapabilityConfigFor(config, config.model).image?.references.maxImages; + if (maxImages === undefined || maxImages < 1 || referenceImages.length <= maxImages) return referenceImages; + return referenceImages.slice(0, maxImages); +} + export { backendProviderConfig }; export function generationTaskMetadata(task: GenerationTask): CanvasNodeMetadata { diff --git a/web/src/pages/canvas/canvas-image-generation-executor.ts b/web/src/pages/canvas/canvas-image-generation-executor.ts index dd21cb950..12e190647 100644 --- a/web/src/pages/canvas/canvas-image-generation-executor.ts +++ b/web/src/pages/canvas/canvas-image-generation-executor.ts @@ -4,7 +4,7 @@ import { NODE_DEFAULT_SIZE } from "@/constant/canvas"; import { canGenerateImageInPlace, findAvailableGenerationGroupPosition, imageGenerationChildPosition, imageGenerationGroupSize } from "@/lib/canvas/canvas-generation-layout"; import { imageMetadata } from "@/lib/canvas/canvas-generation-task-sync"; import { fitNodeSize, nodeSizeFromRatio } from "@/lib/canvas/canvas-node-size"; -import { buildImageGenerationMetadata, getGenerationCount, isGenerationCanceled, runBackendCanvasGenerationTask } from "@/lib/canvas/canvas-project-generation"; +import { buildImageGenerationMetadata, getGenerationCount, isGenerationCanceled, limitCanvasImageReferences, runBackendCanvasGenerationTask } from "@/lib/canvas/canvas-project-generation"; import { CONTENT_MODERATION_ERROR_CODE, generationFailureMetadata, type GenerationFailureMetadata } from "@/lib/generation-error"; import { uploadImage } from "@/services/image-storage"; import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas"; @@ -44,7 +44,7 @@ export async function executeImageGeneration({ const reuseSourceNode = canGenerateImageInPlace(sourceNode); const directCopiedBatch = count > 1 && isImageNode && Boolean(sourceNode?.metadata?.content) && (Boolean(sourceNode?.metadata?.copiedFromNodeId) || sourceNode?.title.endsWith(" Copy")); // 已有图片生成新结果并保留旧版本;参考图只来自入边,避免把旧结果误当成自身输入。 - const referenceImages = generationContext.referenceImages; + const referenceImages = limitCanvasImageReferences(generationConfig, generationContext.referenceImages); const generationType = referenceImages.length ? ("edit" as const) : ("generation" as const); const generationMetadata = buildImageGenerationMetadata(generationType, generationConfig, count, referenceImages); const parentConfig = NODE_DEFAULT_SIZE[isConfigNode ? CanvasNodeType.Config : isImageNode ? CanvasNodeType.Image : CanvasNodeType.Text]; diff --git a/web/src/pages/canvas/use-canvas-generation-retry.ts b/web/src/pages/canvas/use-canvas-generation-retry.ts index 5e82a4db2..2fb50e2a5 100644 --- a/web/src/pages/canvas/use-canvas-generation-retry.ts +++ b/web/src/pages/canvas/use-canvas-generation-retry.ts @@ -15,6 +15,7 @@ import { findRetrySourceNode, generationReferenceUrls, isGenerationCanceled, + limitCanvasImageReferences, resolveMetadataReferences, resolveStoredReferenceImages, runBackendCanvasGenerationTask, @@ -140,7 +141,7 @@ export function useCanvasGenerationRetry({ projectId, domainProjectId, addedSkil message.error("参考图片已丢失,无法继续重试"); return; } - const retryImages = retryReferenceImages || []; + const retryImages = retryMode === "image" ? limitCanvasImageReferences(generationConfig, retryReferenceImages || []) : retryReferenceImages || []; const storedVideoImages = node.type === CanvasNodeType.Video && !context?.referenceImages.length ? await resolveStoredReferenceImages(node.metadata?.references) : []; if (storedVideoImages === null) { markMissingReferences(node.id, setNodes);