fix: 改进流式 write_file 沙箱预览与 Mermaid 旧浏览器兼容

同轮次非末尾 write_file 也能自动打开沙箱并跳过 JSON 大文件预览;Mermaid 改用 SVG 标签;agentfx 强制先写 md 再写 json。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
董宏凯andCursor committed 2026-08-28 16:21:39 +08:00
1 parent 875001a8c0
commit 832e180c52
7 files changed
+236 -10

No files matched your search

@@ -18,6 +18,7 @@ import {
listThreadArtifacts,
mergeArtifactPaths,
} from "@/core/artifacts/listing";
import { latestInFlightWriteFilePreview } from "@/core/artifacts/write-file-in-flight";
import { getBackendBaseURL } from "@/core/config";
import { isThreadRagModeLocked, useLocalSettings } from "@/core/settings";
import { isSingleRoundRagMessage } from "@/core/threads/use-single-round-rag";
@@ -174,6 +175,7 @@ const ChatBox: React.FC<{
deselect,
selectedArtifact,
selectedArtifactKey,
openStreamedArtifact,
} = useArtifacts();
const [autoSelectFirstArtifact, setAutoSelectFirstArtifact] = useState(true);
@@ -424,6 +426,26 @@ const ChatBox: React.FC<{
disableArtifacts,
]);
// Live sandbox: open as soon as any in-flight write_file has a path or
// the first content bytes — not only when that tool is the last CoT step.
// Agentfx (and other agents) often emit write_file + present_files/bash in
// the same turn; the collapsed earlier write would otherwise never auto-open.
const streamingWritePreview = useMemo(
() =>
disableArtifacts || !thread.isLoading
? null
: latestInFlightWriteFilePreview(thread.messages ?? []),
[disableArtifacts, thread.isLoading, thread.messages],
);
useEffect(() => {
if (!streamingWritePreview) return;
openStreamedArtifact(
streamingWritePreview.artifactPath,
streamingWritePreview.previewKey,
);
setSideTab("document");
}, [openStreamedArtifact, streamingWritePreview]);
const directoryModeWasEnabledRef = useRef(artifactDirectoryModeEnabled);
useEffect(() => {
const wasEnabled = directoryModeWasEnabledRef.current;
@@ -42,6 +42,7 @@ import {
import {
buildWriteFileVirtualUrl,
hasCompleteArtifactExtension,
languageOfStreamingArtifact,
normalizeStreamingArtifactPath,
provisionalWriteFilePath,
} from "@/core/artifacts/streaming-write-preview";
@@ -754,7 +755,6 @@ function ArtifactWriteToolCall({
args,
result,
description,
isLast,
isLoading,
}: {
id?: string;
@@ -793,19 +793,20 @@ function ArtifactWriteToolCall({
!artifactPath ||
!previewKey ||
!isLoading ||
!isLast ||
result !== undefined
result !== undefined ||
!sourcePath ||
!languageOfStreamingArtifact(sourcePath)
) {
return;
}
openStreamedArtifact(artifactPath, previewKey);
}, [
artifactPath,
isLast,
isLoading,
openStreamedArtifact,
previewKey,
result,
sourcePath,
]);
return (