feat(roundtable): 第二/三步沙箱 md 文件支持用户编辑
复用主聊天页同款 ArtifactFileDetail 编辑能力:新增 allowVirtualMarkdownEdit 开关,圆桌沙箱里 write-file 虚拟 md 在流式结束后切回真实 artifacts API (可加载 + PATCH 保存),由 Step2SandboxLayout 与 HighFidelityReport 启用。 主聊天页等其它调用方默认关闭、行为不变。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
8751ee7361
commit
49101ef0e8
3 files changed
+31
-5
No files matched your search
@@ -121,12 +121,19 @@ export function ArtifactFileDetail({
|
||||
filepath: filepathFromProps,
|
||||
threadId,
|
||||
onClose,
|
||||
allowVirtualMarkdownEdit = false,
|
||||
}: {
|
||||
className?: string;
|
||||
filepath: string;
|
||||
threadId: string;
|
||||
/** 覆盖默认关闭行为(仅 setOpen(false));圆桌 Step3 文件预览用于退出沙箱模式。 */
|
||||
onClose?: () => void;
|
||||
/**
|
||||
* 圆桌沙箱(Step2/Step3)用:流式结束后,把 `write-file:` 虚拟 md 预览切回真实
|
||||
* artifacts API(可加载 + PATCH 保存),从而支持用户编辑(对齐主聊天页 md 可编辑)。
|
||||
* 默认 false —— 主聊天页等其它调用方行为不变。
|
||||
*/
|
||||
allowVirtualMarkdownEdit?: boolean;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const { artifacts, setOpen, select } = useArtifacts();
|
||||
@@ -141,10 +148,6 @@ export function ArtifactFileDetail({
|
||||
}
|
||||
return filepathFromProps;
|
||||
}, [filepathFromProps, isWriteFileVirtual]);
|
||||
/** write_file 流式预览走 tool args 文本;图片等二进制产物始终走 artifacts API。 */
|
||||
const useWriteFileStreaming = useMemo(() => {
|
||||
return isWriteFileVirtual && !isImageFile(filepath);
|
||||
}, [filepath, isWriteFileVirtual]);
|
||||
const isSkillFile = useMemo(() => {
|
||||
return filepath.endsWith(".skill");
|
||||
}, [filepath]);
|
||||
@@ -153,6 +156,24 @@ export function ArtifactFileDetail({
|
||||
const isSpreadsheetFile = useMemo(() => {
|
||||
return /\.xlsx$/i.test(filepath);
|
||||
}, [filepath]);
|
||||
// 圆桌沙箱:write_file 虚拟预览的 md 在流式结束(thread 非 loading)后,切回真实
|
||||
// artifacts API 加载并允许编辑/保存。流式进行中仍走内存 stub 只读预览;仅
|
||||
// allowVirtualMarkdownEdit 开启的调用方(Step2/Step3 沙箱)生效,主聊天页不受影响。
|
||||
const editVirtualMarkdown = useMemo(() => {
|
||||
return (
|
||||
allowVirtualMarkdownEdit &&
|
||||
isWriteFileVirtual &&
|
||||
!isImageFile(filepath) &&
|
||||
!isMock &&
|
||||
!thread.isLoading &&
|
||||
checkCodeFile(filepath).language === "markdown"
|
||||
);
|
||||
}, [allowVirtualMarkdownEdit, isWriteFileVirtual, filepath, isMock, thread.isLoading]);
|
||||
/** write_file 流式预览走 tool args 文本;图片等二进制产物始终走 artifacts API;
|
||||
* 圆桌结束后可编辑的 md(editVirtualMarkdown)亦回到真实 API(可加载 + PATCH 保存)。 */
|
||||
const useWriteFileStreaming = useMemo(() => {
|
||||
return isWriteFileVirtual && !isImageFile(filepath) && !editVirtualMarkdown;
|
||||
}, [filepath, isWriteFileVirtual, editVirtualMarkdown]);
|
||||
const { isCodeFile, language } = useMemo(() => {
|
||||
if (useWriteFileStreaming) {
|
||||
let nextLanguage = checkCodeFile(filepath).language;
|
||||
@@ -173,7 +194,10 @@ export function ArtifactFileDetail({
|
||||
}, [language]);
|
||||
const { content, isApplyingEdit } = useArtifactContent({
|
||||
threadId,
|
||||
filepath: filepathFromProps,
|
||||
// editVirtualMarkdown:用解码后的真实路径走 artifacts API(而非 write-file 虚拟
|
||||
// URL),这样保存后 useUpdateArtifactContent 写入的查询缓存才能命中,编辑内容
|
||||
// 不会被旧的内存 stub 值覆盖回退。
|
||||
filepath: editVirtualMarkdown ? filepath : filepathFromProps,
|
||||
enabled: isCodeFile && !useWriteFileStreaming,
|
||||
});
|
||||
|
||||
|
||||
@@ -1009,6 +1009,7 @@ export const HighFidelityReport: React.FC<HighFidelityReportProps> = ({
|
||||
filepath={fileSandboxVirtualUrl}
|
||||
threadId={fileSandboxTarget.threadId}
|
||||
onClose={handleCloseFileSandbox}
|
||||
allowVirtualMarkdownEdit
|
||||
/>
|
||||
</ThreadContext.Provider>
|
||||
)}
|
||||
|
||||
@@ -115,6 +115,7 @@ export function Step2SandboxLayout({
|
||||
filepath={selectedArtifact}
|
||||
threadId={previewThreadId}
|
||||
onClose={artifactsFill && onArtifactsClose ? handleArtifactsClose : undefined}
|
||||
allowVirtualMarkdownEdit
|
||||
/>
|
||||
) : (
|
||||
<div className="relative flex size-full justify-center">
|
||||
|
||||
Reference in new issue
Block a user