优化生图占位图显示时机先展示Agent对话

This commit is contained in:
Your Name 2026-02-08 22:22:21 +08:00
parent 3f61b27057
commit e038ba3593

View File

@ -147,6 +147,12 @@ function PureMessages({
imageGenerationPhase === "queued" || imageGenerationPhase === "queued" ||
imageGenerationPhase === "processing" || imageGenerationPhase === "processing" ||
imageGenerationPhase === "finalizing"; imageGenerationPhase === "finalizing";
const stripInternalMarkers = (text: string) =>
text
.replace(/\n*<!-- GENERATING_IMAGE -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_START -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_END -->\n*/g, "")
.trim();
useEffect(() => { useEffect(() => {
return () => { return () => {
@ -288,11 +294,16 @@ function PureMessages({
// - 收到 AI 文字回复后 3 秒: true(开始显示生图占位图) // - 收到 AI 文字回复后 3 秒: true(开始显示生图占位图)
// - 收到图片消息: false(隐藏占位图) // - 收到图片消息: false(隐藏占位图)
// 检查最后一条消息是否是 AI 的文字回复(包含 GENERATING_IMAGE 标记) // 检查当前轮次是否已收到 AI 文字回复(只看最后一条用户消息之后)
const hasAssistantTextReply = messages.some(msg => const lastUserIndex = messages.findLastIndex((m) => m.role === "user");
msg.role === "assistant" && msg.parts?.some( const assistantMessagesAfterUser = lastUserIndex >= 0
(part: any) => part.type === "text" && part.text?.includes("<!-- GENERATING_IMAGE -->") ? messages.slice(lastUserIndex + 1).filter((m) => m.role === "assistant")
) : messages.filter((m) => m.role === "assistant");
const hasAssistantTextReply = assistantMessagesAfterUser.some((msg) =>
msg.parts?.some((part: any) => {
if (part.type !== "text" || !part.text) return false;
return stripInternalMarkers(part.text).length > 0;
})
); );
if (hasImageContent) { if (hasImageContent) {
@ -353,22 +364,19 @@ function PureMessages({
const isAutoModeWithImage = selectedModelId === "auto" && const isAutoModeWithImage = selectedModelId === "auto" &&
lastUserMessage?.parts?.some((p: any) => p.type === "file" || p.type === "image"); lastUserMessage?.parts?.some((p: any) => p.type === "file" || p.type === "image");
const hasAssistantTextReplyWithContent = messages.some(msg => const lastUserIndex = messages.findLastIndex((m) => m.role === "user");
msg.role === "assistant" && msg.parts?.some((part: any) => { const assistantMessagesAfterUser = lastUserIndex >= 0
? messages.slice(lastUserIndex + 1).filter((m) => m.role === "assistant")
: messages.filter((m) => m.role === "assistant");
const hasAssistantTextReplyWithContent = assistantMessagesAfterUser.some((msg) =>
msg.parts?.some((part: any) => {
if (part.type !== "text" || !part.text) return false; if (part.type !== "text" || !part.text) return false;
const cleanedText = part.text return stripInternalMarkers(part.text).length > 0;
.replace(/\n*<!-- GENERATING_IMAGE -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_START -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_END -->\n*/g, "")
.trim();
return cleanedText.length > 0;
}) })
); );
let hasImageContent = false; let hasImageContent = false;
if (isAutoModeWithImage) { if (isAutoModeWithImage) {
const lastUserIndex = messages.findLastIndex(m => m.role === "user");
const assistantMessagesAfterUser = messages.slice(lastUserIndex + 1).filter(m => m.role === "assistant");
hasImageContent = assistantMessagesAfterUser.some(msg => hasImageContent = assistantMessagesAfterUser.some(msg =>
msg.parts?.some((part: any) => part.type === "text" && part.text && ( msg.parts?.some((part: any) => part.type === "text" && part.text && (
part.text.includes("![thumb|") || part.text.includes("![thumb|") ||
@ -587,19 +595,24 @@ function PureMessages({
(part: any) => part.type === "text" && part.text?.includes("<!-- IMAGE_GENERATION_END -->") (part: any) => part.type === "text" && part.text?.includes("<!-- IMAGE_GENERATION_END -->")
) )
); );
const hasAssistantTextReplyWithContent = messages.some(msg => const assistantMessagesAfterUser = lastUserIndexForMarkers >= 0
msg.role === "assistant" && msg.parts?.some((part: any) => { ? messages.slice(lastUserIndexForMarkers + 1).filter((msg) => msg.role === "assistant")
: messages.filter((msg) => msg.role === "assistant");
const hasAssistantTextReplyWithContent = assistantMessagesAfterUser.some((msg) =>
msg.parts?.some((part: any) => {
if (part.type !== "text" || !part.text) return false; if (part.type !== "text" || !part.text) return false;
const cleanedText = part.text return stripInternalMarkers(part.text).length > 0;
.replace(/\n*<!-- GENERATING_IMAGE -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_START -->\n*/g, "")
.replace(/\n*<!-- IMAGE_GENERATION_END -->\n*/g, "")
.trim();
return cleanedText.length > 0;
}) })
); );
const shouldWaitForAgentReplyBeforeImagePlaceholder =
userMessageHasImage &&
(isAutoMode || showGemini || showVolcano || showAlibabaImage) &&
!hasAssistantTextReplyWithContent;
if (showVideo) return <QianwenVideoLoading />; if (showVideo) return <QianwenVideoLoading />;
if (shouldWaitForAgentReplyBeforeImagePlaceholder) {
return <ThinkingMessage />;
}
if (showGemini) return <GeminiImageLoading imageCount={imageCount} />; if (showGemini) return <GeminiImageLoading imageCount={imageCount} />;
if (showVolcano) return <VolcanoVisionLoading imageCount={imageCount} />; if (showVolcano) return <VolcanoVisionLoading imageCount={imageCount} />;
if (showAlibabaImage) { if (showAlibabaImage) {