fix: stabilize agent mode state syncing
This commit is contained in:
parent
337fd15471
commit
af7e98a4dc
@ -111,6 +111,47 @@ interface AgentModeReferenceSearchResponse {
|
||||
};
|
||||
}
|
||||
|
||||
function areImageGenerationParamsEqual(
|
||||
left: ImageGenerationParams,
|
||||
right: ImageGenerationParams
|
||||
) {
|
||||
return (
|
||||
left.aspectRatio === right.aspectRatio &&
|
||||
left.imageSize === right.imageSize &&
|
||||
(left.imageCount || 1) === (right.imageCount || 1) &&
|
||||
left.size === right.size &&
|
||||
left.negativePrompt === right.negativePrompt &&
|
||||
left.promptExtend === right.promptExtend &&
|
||||
left.watermark === right.watermark &&
|
||||
left.seed === right.seed
|
||||
);
|
||||
}
|
||||
|
||||
function arePickedAttachmentsEqual(
|
||||
left: Array<PickedAttachment | null>,
|
||||
right: Array<PickedAttachment | null>
|
||||
) {
|
||||
if (left === right) return true;
|
||||
if (left.length !== right.length) return false;
|
||||
|
||||
for (let index = 0; index < left.length; index += 1) {
|
||||
const leftItem = left[index];
|
||||
const rightItem = right[index];
|
||||
if (!leftItem && !rightItem) continue;
|
||||
if (!leftItem || !rightItem) return false;
|
||||
if (
|
||||
leftItem.url !== rightItem.url ||
|
||||
leftItem.name !== rightItem.name ||
|
||||
leftItem.contentType !== rightItem.contentType ||
|
||||
leftItem.assetId !== rightItem.assetId
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
type ToolStepKey =
|
||||
| "preset"
|
||||
| "brand-model"
|
||||
@ -551,15 +592,24 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
|
||||
useEffect(() => {
|
||||
if (normalizedIncomingWorkspaceState.selectedModelId) {
|
||||
setSelectedModelId(normalizedIncomingWorkspaceState.selectedModelId);
|
||||
const nextModelId = normalizedIncomingWorkspaceState.selectedModelId;
|
||||
setSelectedModelId((current) =>
|
||||
current === nextModelId ? current : nextModelId
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (selectedAgentPreset?.defaultModelId) {
|
||||
setSelectedModelId(selectedAgentPreset.defaultModelId);
|
||||
const nextModelId = selectedAgentPreset.defaultModelId;
|
||||
setSelectedModelId((current) =>
|
||||
current === nextModelId ? current : nextModelId
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (modelsData?.defaultModelId) {
|
||||
setSelectedModelId(modelsData.defaultModelId);
|
||||
const nextModelId = modelsData.defaultModelId;
|
||||
setSelectedModelId((current) =>
|
||||
current === nextModelId ? current : nextModelId
|
||||
);
|
||||
}
|
||||
}, [
|
||||
modelsData?.defaultModelId,
|
||||
@ -570,7 +620,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
// 初始化附件
|
||||
useEffect(() => {
|
||||
if (!hasAgentUploadSlots) {
|
||||
setAttachments([]);
|
||||
setAttachments((current) => (current.length === 0 ? current : []));
|
||||
return;
|
||||
}
|
||||
const nextSlots: Array<PickedAttachment | null> = Array.from(
|
||||
@ -603,7 +653,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
result[index] = nextSlots[index] as PickedAttachment;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return arePickedAttachmentsEqual(current, result) ? current : result;
|
||||
});
|
||||
}, [
|
||||
agentUploadSlots.length,
|
||||
@ -647,7 +697,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
slots[modelSlotIndex] = null;
|
||||
}
|
||||
|
||||
return slots;
|
||||
return arePickedAttachmentsEqual(current, slots) ? current : slots;
|
||||
});
|
||||
|
||||
lastSyncedBrandModelUrlRef.current = nextAttachment?.url || null;
|
||||
@ -812,8 +862,8 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
}
|
||||
workspaceStateSignatureRef.current = incomingSignature;
|
||||
setInput(normalizedIncomingWorkspaceState.input);
|
||||
setAttachments(
|
||||
normalizedIncomingWorkspaceState.attachments.map((item) =>
|
||||
setAttachments((current) => {
|
||||
const nextAttachments = normalizedIncomingWorkspaceState.attachments.map((item) =>
|
||||
item
|
||||
? {
|
||||
url: item.url,
|
||||
@ -822,13 +872,20 @@ export function AgentGenerationWorkspaceDarkV2({
|
||||
assetId: item.assetId || undefined,
|
||||
}
|
||||
: null
|
||||
)
|
||||
);
|
||||
setSelectedModelId(normalizedIncomingWorkspaceState.selectedModelId || "auto");
|
||||
setImageParams({
|
||||
aspectRatio: normalizedIncomingWorkspaceState.imageParams?.aspectRatio || "auto",
|
||||
imageSize: normalizedIncomingWorkspaceState.imageParams?.imageSize || "2K",
|
||||
imageCount: normalizedIncomingWorkspaceState.imageParams?.imageCount || 1,
|
||||
);
|
||||
return arePickedAttachmentsEqual(current, nextAttachments) ? current : nextAttachments;
|
||||
});
|
||||
setSelectedModelId((current) => {
|
||||
const nextModelId = normalizedIncomingWorkspaceState.selectedModelId || "auto";
|
||||
return current === nextModelId ? current : nextModelId;
|
||||
});
|
||||
setImageParams((current) => {
|
||||
const nextParams = {
|
||||
aspectRatio: normalizedIncomingWorkspaceState.imageParams?.aspectRatio || "auto",
|
||||
imageSize: normalizedIncomingWorkspaceState.imageParams?.imageSize || "2K",
|
||||
imageCount: normalizedIncomingWorkspaceState.imageParams?.imageCount || 1,
|
||||
};
|
||||
return areImageGenerationParamsEqual(current, nextParams) ? current : nextParams;
|
||||
});
|
||||
}, [normalizedIncomingWorkspaceState]);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Link2, Scan, SlidersHorizontal, Sparkles } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
@ -89,6 +89,28 @@ export function ImageParamsBar({
|
||||
showInlineDivider = true,
|
||||
imageGenConfig,
|
||||
}: ImageParamsBarProps) {
|
||||
const hasNormalizedParamDiff = (
|
||||
source: Partial<ImageGenerationParams> | undefined,
|
||||
normalized: ImageGenerationParams
|
||||
) => {
|
||||
if (!source) return false;
|
||||
|
||||
const keys: Array<keyof ImageGenerationParams> = [
|
||||
"aspectRatio",
|
||||
"imageSize",
|
||||
"imageCount",
|
||||
"size",
|
||||
"negativePrompt",
|
||||
"promptExtend",
|
||||
"watermark",
|
||||
"seed",
|
||||
];
|
||||
|
||||
return keys.some(
|
||||
(key) => source[key] !== undefined && source[key] !== normalized[key]
|
||||
);
|
||||
};
|
||||
|
||||
const getImageCountOptions = () => {
|
||||
// RUXA 当前按单图任务处理(优先级最高)
|
||||
if (providerType === "ruxa-image" || providerType === "openai-image" || providerType === "midjourney") {
|
||||
@ -228,33 +250,32 @@ export function ImageParamsBar({
|
||||
);
|
||||
};
|
||||
|
||||
// 🆕 监听 initialParams 变化,确保状态同步
|
||||
// 仅同步展示状态;只有确实发生参数校正时才回写父层,避免和父组件互相触发更新。
|
||||
useEffect(() => {
|
||||
console.log("[ImageParamsBar] Mount/Update - initialParams:", initialParams);
|
||||
const rawParams = {
|
||||
aspectRatio: "auto",
|
||||
imageSize: "2K",
|
||||
imageCount: 1,
|
||||
promptExtend: true,
|
||||
watermark: false,
|
||||
...(initialParams || {}),
|
||||
} as ImageGenerationParams;
|
||||
const nextParams = buildBaseParams(initialParams);
|
||||
setParams((prevParams) => (isSameParams(prevParams, nextParams) ? prevParams : nextParams));
|
||||
if (initialParams !== undefined && onParamsChange && !isSameParams(rawParams, nextParams)) {
|
||||
if (onParamsChange && hasNormalizedParamDiff(initialParams, nextParams)) {
|
||||
onParamsChange(nextParams);
|
||||
}
|
||||
}, [initialParams, providerType, imageGenConfig?.maxImages, imageGenConfig?.supports1K, imageGenConfig?.supports2K, imageGenConfig?.supports4K]);
|
||||
}, [
|
||||
imageGenConfig?.maxImages,
|
||||
imageGenConfig?.supports1K,
|
||||
imageGenConfig?.supports2K,
|
||||
imageGenConfig?.supports4K,
|
||||
initialParams,
|
||||
onParamsChange,
|
||||
providerType,
|
||||
]);
|
||||
|
||||
const updateParam = <K extends keyof ImageGenerationParams>(
|
||||
key: K,
|
||||
value: ImageGenerationParams[K]
|
||||
) => {
|
||||
const newParams = clampParamsByProvider({ ...params, [key]: value });
|
||||
console.log("[ImageParamsBar] Updating param:", key, "=", value);
|
||||
console.log("[ImageParamsBar] New params:", newParams);
|
||||
setParams(newParams);
|
||||
onParamsChange?.(newParams);
|
||||
setParams((prevParams) => (isSameParams(prevParams, newParams) ? prevParams : newParams));
|
||||
if (!isSameParams(params, newParams)) {
|
||||
onParamsChange?.(newParams);
|
||||
}
|
||||
};
|
||||
|
||||
// 内联模式:只返回参数按钮,嵌入工具栏
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user