diff --git a/components/elements/response.tsx b/components/elements/response.tsx
index b908c4b7e..82deb547e 100644
--- a/components/elements/response.tsx
+++ b/components/elements/response.tsx
@@ -905,11 +905,17 @@ export const Response = ({
),
};
- const renderImagePreview = (src: string, alt: string | undefined, key: string) => (
+ const renderImagePreview = (
+ src: string,
+ alt: string | undefined,
+ key: string,
+ compactGrid = false
+ ) => (
);
+ const renderImageGrid = (
+ images: Array<{ alt?: string; src: string }>,
+ keyPrefix: string
+ ) => {
+ if (images.length === 0) return null;
+ if (images.length === 1) {
+ const image = images[0];
+ return renderImagePreview(
+ image.src,
+ image.alt,
+ `${image.src}-${processingKey}-${keyPrefix}-single`
+ );
+ }
+
+ const gridClassName =
+ images.length === 2
+ ? "grid-cols-2 sm:max-w-[640px]"
+ : images.length === 3
+ ? "grid-cols-2 sm:grid-cols-3 sm:max-w-[780px]"
+ : "grid-cols-2 sm:grid-cols-4 sm:max-w-[920px]";
+
+ return (
+
+ {images.map((image, index) => (
+
+ {renderImagePreview(
+ image.src,
+ image.alt,
+ `${image.src}-${processingKey}-${keyPrefix}-grid-${index}`,
+ true
+ )}
+
+ ))}
+
+ );
+ };
+
const renderTextSegment = (text: string, keyPrefix: string): ReactNode => {
if (!text.trim()) return null;
@@ -937,20 +986,31 @@ export const Response = ({
const hasImageSegments = segments.some((segment) => segment.type === "image");
if (hasImageSegments) {
- return segments.map((segment, index) => {
+ const nodes: ReactNode[] = [];
+ let pendingImages: Array<{ alt?: string; src: string }> = [];
+ const flushImages = (index: number) => {
+ if (pendingImages.length === 0) return;
+ nodes.push(
+ renderImageGrid(pendingImages, `${keyPrefix}-images-${index}`)
+ );
+ pendingImages = [];
+ };
+
+ segments.forEach((segment, index) => {
if (segment.type === "image") {
- return renderImagePreview(
- segment.src,
- segment.alt,
- `${segment.src}-${processingKey}-${keyPrefix}-${index}`
- );
+ pendingImages.push({
+ alt: segment.alt,
+ src: segment.src,
+ });
+ return;
}
if (!segment.value.trim()) {
- return null;
+ return;
}
- return (
+ flushImages(index);
+ nodes.push(
);
});
+ flushImages(segments.length);
+ return nodes;
}
}
diff --git a/components/image-preview.tsx b/components/image-preview.tsx
index 6908df6fd..1750c9332 100644
--- a/components/image-preview.tsx
+++ b/components/image-preview.tsx
@@ -42,7 +42,8 @@ export function ImagePreview({
isProcessingExtend,
isProcessingAngleEdit,
isProcessingWatermarkRemove,
- imageIndex
+ imageIndex,
+ compactGrid = false
}: {
src: string;
alt?: string;
@@ -64,6 +65,7 @@ export function ImagePreview({
isProcessingAngleEdit?: boolean;
isProcessingWatermarkRemove?: boolean;
imageIndex?: number;
+ compactGrid?: boolean;
}) {
const [isOpen, setIsOpen] = useState(false);
const [isAnnotationMode, setIsAnnotationMode] = useState(false);
@@ -293,16 +295,26 @@ export function ImagePreview({
return (
<>
{/* 缩略图(显示压缩后的缩略图)*/}
-
+

1;
const result = await generateCanvasImage({
prompt,
negativePrompt: params.imageParams?.negativePrompt,
model: params.finalModelId,
ownerKey: params.userId,
+ debugLabel: "direct-agent-image-generation",
+ debugMeta: {
+ agentIgnoreModelMaxImages: shouldIgnoreModelMaxImages,
+ requestedAgentImageCount: imageCount ?? null,
+ },
aspectRatio:
params.imageParams?.aspectRatio || params.defaultImageQualityParams?.aspectRatio,
imageSize,
imageCount,
+ ignoreModelMaxImages: shouldIgnoreModelMaxImages,
referenceImages: params.referenceImageUrls,
});
diff --git a/lib/canvas/generate-image.ts b/lib/canvas/generate-image.ts
index e29df494e..6a82b853e 100644
--- a/lib/canvas/generate-image.ts
+++ b/lib/canvas/generate-image.ts
@@ -116,6 +116,7 @@ export interface CanvasGenerateImageRequest {
ownerKey?: string;
debugLabel?: string;
debugMeta?: Record
;
+ ignoreModelMaxImages?: boolean;
localEditComposite?: CanvasLocalEditCompositeConfig;
scaleAdjustPatchComposite?: CanvasScaleAdjustPatchCompositeConfig;
scaleAdjustVerification?: CanvasScaleAdjustVerificationConfig;
@@ -3167,12 +3168,14 @@ function normalizeCanvasImageParamsByModel(params: {
imageCount: number;
imageSize: string;
imageGenConfig: CanvasImageGenConfig | null | undefined;
+ ignoreModelMaxImages?: boolean;
}) {
- const maxImages =
+ const configuredMaxImages =
typeof params.imageGenConfig?.maxImages === "number" &&
Number.isFinite(params.imageGenConfig.maxImages)
? Math.max(1, Math.floor(params.imageGenConfig.maxImages))
: 12;
+ const maxImages = params.ignoreModelMaxImages ? 12 : configuredMaxImages;
const imageCount = Math.max(1, Math.min(maxImages, Math.floor(params.imageCount)));
const requestedSize = normalizeCanvasImageSizeValue(params.imageSize);
@@ -3635,6 +3638,7 @@ export async function generateCanvasImage(
imageCount: requestedImageCount,
imageSize: requestedImageSize,
imageGenConfig: selectedModel.model.imageGenConfig as CanvasImageGenConfig | null | undefined,
+ ignoreModelMaxImages: request.ignoreModelMaxImages === true,
});
const imageSize = normalizedImageParams.imageSize;
const imageCount =