fix: improve canvas agent response rendering
This commit is contained in:
parent
0b5866bb94
commit
82876977aa
@ -11976,18 +11976,6 @@ export async function POST(request: Request) {
|
||||
},
|
||||
"protocol:request"
|
||||
);
|
||||
writeAgentProgressChunk(
|
||||
dataStream,
|
||||
{
|
||||
stage: "planning",
|
||||
currentStep: "analyze",
|
||||
title: "正在理解你的需求",
|
||||
message: "我会先结合当前图、历史结果和画布上下文整理执行方案。",
|
||||
toolName: "agentConversation",
|
||||
capability: smartAutoExecution?.preferredCapability || undefined,
|
||||
},
|
||||
"chat-default:progress-planning",
|
||||
);
|
||||
writeCurrentAgentTargetLockChunk(dataStream, "chat-default:target-lock");
|
||||
for (const event of pendingProtocolDebugEvents) {
|
||||
writeProtocolDebugChunk(
|
||||
|
||||
@ -91,6 +91,7 @@ import { getCanvasSkillIconComponent } from "@/components/canvas/canvas-skill-ic
|
||||
import { ImageParamsBar, type ImageGenerationParams } from "@/components/image-params-bar";
|
||||
import { VideoParamsBar, type VideoGenerationParams } from "@/components/video-params-bar";
|
||||
import { ImageGenerationLoading } from "@/components/image-generation-loading";
|
||||
import { Response } from "@/components/elements/response";
|
||||
import type { VideoToolCapabilityContract } from "@/types/video-tool-capability";
|
||||
import { DetailUiValidationPanel } from "@/components/canvas/DetailUiValidationPanel";
|
||||
import { DetailSurfaceInspectorPanel } from "@/components/canvas/DetailSurfaceInspectorPanel";
|
||||
@ -1019,6 +1020,7 @@ type CanvasTypewriterTextProps = {
|
||||
typingKey: string;
|
||||
enabled: boolean;
|
||||
className?: string;
|
||||
renderMarkdown?: boolean;
|
||||
onActiveChange?: (typingKey: string, active: boolean) => void;
|
||||
onComplete?: (typingKey: string) => void;
|
||||
};
|
||||
@ -1028,6 +1030,7 @@ function CanvasTypewriterText({
|
||||
typingKey,
|
||||
enabled,
|
||||
className,
|
||||
renderMarkdown = false,
|
||||
onActiveChange,
|
||||
onComplete,
|
||||
}: CanvasTypewriterTextProps) {
|
||||
@ -1074,18 +1077,33 @@ function CanvasTypewriterText({
|
||||
};
|
||||
}, [content, enabled, onActiveChange, onComplete, typingKey]);
|
||||
|
||||
if (renderMarkdown) {
|
||||
return <Response className={className}>{displayText}</Response>;
|
||||
}
|
||||
|
||||
return <div className={className}>{displayText}</div>;
|
||||
}
|
||||
|
||||
function normalizeCanvasAgentText(value: string): string {
|
||||
return String(value || "")
|
||||
.replace(/\r\n/g, "\n")
|
||||
.replace(/^#{1,6}\s*/gm, "")
|
||||
.replace(/^\*\*(.+)\*\*$/gm, "$1")
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function hasCanvasRenderableMarkdown(value: string): boolean {
|
||||
const text = String(value || "");
|
||||
if (!text) return false;
|
||||
|
||||
return (
|
||||
/(^|\n)\s*#{1,6}\s+/.test(text) ||
|
||||
/\*\*[^*]+\*\*/.test(text) ||
|
||||
/(^|\n)\s*[-*+]\s+/.test(text) ||
|
||||
/(^|\n)\s*\d+\.\s+/.test(text) ||
|
||||
/\[[^\]]+\]\([^)]+\)/.test(text)
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeCanvasSectionTitle(line: string): string {
|
||||
let normalized = line.trim();
|
||||
if (!normalized) return "";
|
||||
@ -9285,8 +9303,7 @@ export function CanvasChatPanel({
|
||||
!isPresetAgentSelection &&
|
||||
Boolean(activeAgentProgress) &&
|
||||
!(activeAgentProgress?.stage === "clarify" && isAgentTargetClarificationActive) &&
|
||||
(isLoading ||
|
||||
activeAgentProgress?.stage === "clarify" ||
|
||||
(activeAgentProgress?.stage === "clarify" ||
|
||||
activeAgentProgress?.stage === "failed");
|
||||
const agentTargetLockPreviewItems = useMemo(() => {
|
||||
if (!activeAgentTargetLock) return [] as AgentTargetLockRefPreview[];
|
||||
@ -10111,11 +10128,13 @@ export function CanvasChatPanel({
|
||||
const shouldAnimateAnalysis =
|
||||
shouldTypeAssistantMessage &&
|
||||
Boolean(analysisSection?.analysis) &&
|
||||
!hasCanvasRenderableMarkdown(analysisSection?.analysis || "") &&
|
||||
!typedAssistantSections[analysisTypingKey];
|
||||
const shouldAnimatePlainText =
|
||||
shouldTypeAssistantMessage &&
|
||||
!analysisSection &&
|
||||
Boolean(plainText) &&
|
||||
!hasCanvasRenderableMarkdown(plainText) &&
|
||||
!typedAssistantSections[plainTextTypingKey];
|
||||
const shouldShowDoneSummary =
|
||||
!isDetailGenerationMode &&
|
||||
@ -10123,12 +10142,12 @@ export function CanvasChatPanel({
|
||||
!plainText.includes(CANVAS_IMAGE_DONE_SUMMARY) &&
|
||||
!isLatestAssistantDuringGeneration;
|
||||
const renderPlainText = (text: string, key: string) => (
|
||||
<div
|
||||
<Response
|
||||
key={key}
|
||||
className="whitespace-pre-wrap break-words [overflow-wrap:anywhere]"
|
||||
className="break-words [overflow-wrap:anywhere]"
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
</Response>
|
||||
);
|
||||
|
||||
return (
|
||||
@ -10185,6 +10204,7 @@ export function CanvasChatPanel({
|
||||
typingKey={analysisTypingKey}
|
||||
enabled={shouldAnimateAnalysis}
|
||||
className="whitespace-pre-wrap break-words [overflow-wrap:anywhere]"
|
||||
renderMarkdown
|
||||
onActiveChange={handleTypewriterActiveChange}
|
||||
onComplete={handleTypewriterComplete}
|
||||
/>
|
||||
@ -10200,6 +10220,7 @@ export function CanvasChatPanel({
|
||||
typingKey={plainTextTypingKey}
|
||||
enabled={shouldAnimatePlainText}
|
||||
className="break-words [overflow-wrap:anywhere]"
|
||||
renderMarkdown
|
||||
onActiveChange={handleTypewriterActiveChange}
|
||||
onComplete={handleTypewriterComplete}
|
||||
/>
|
||||
@ -11348,11 +11369,7 @@ export function CanvasChatPanel({
|
||||
<span>Auto Agent</span>
|
||||
</div>
|
||||
)}
|
||||
{!isPresetAgentSelection ? (
|
||||
<div className="inline-flex items-center rounded-full bg-[#f4f5f7] px-3 py-1.5 text-xs text-[#5b6472] dark:bg-white/8 dark:text-zinc-300">
|
||||
直接对话即可,也可上传图片让我分析、修图或继续生成
|
||||
</div>
|
||||
) : selectedAgentPreset?.type === "text" ? (
|
||||
{isPresetAgentSelection && selectedAgentPreset?.type === "text" ? (
|
||||
<div className="inline-flex items-center rounded-full bg-[#f4f5f7] px-3 py-1.5 text-xs text-[#5b6472] dark:bg-white/8 dark:text-zinc-300">
|
||||
可上传图片做分析,也可直接输入文案需求
|
||||
</div>
|
||||
|
||||
@ -776,13 +776,12 @@ export const ThinkingMessage = () => {
|
||||
</div>
|
||||
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
{/* 简洁明了的文本 + 动态点 */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-base font-medium text-foreground">AI 正在分析中</span>
|
||||
<span className="flex gap-1">
|
||||
<span className="h-2 w-2 rounded-full bg-foreground animate-bounce" style={{ animationDelay: '0ms' }} />
|
||||
<span className="h-2 w-2 rounded-full bg-foreground animate-bounce" style={{ animationDelay: '150ms' }} />
|
||||
<span className="h-2 w-2 rounded-full bg-foreground animate-bounce" style={{ animationDelay: '300ms' }} />
|
||||
<div className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
||||
<span className="sr-only">正在处理</span>
|
||||
<span className="flex gap-1" aria-hidden="true">
|
||||
<span className="h-2 w-2 rounded-full bg-foreground/65 animate-bounce" style={{ animationDelay: '0ms' }} />
|
||||
<span className="h-2 w-2 rounded-full bg-foreground/65 animate-bounce" style={{ animationDelay: '150ms' }} />
|
||||
<span className="h-2 w-2 rounded-full bg-foreground/65 animate-bounce" style={{ animationDelay: '300ms' }} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user