diff --git a/frontend-web/src/roundtable-planning/components/MessageStepsCard.tsx b/frontend-web/src/roundtable-planning/components/MessageStepsCard.tsx index 73463705..95a281a9 100644 --- a/frontend-web/src/roundtable-planning/components/MessageStepsCard.tsx +++ b/frontend-web/src/roundtable-planning/components/MessageStepsCard.tsx @@ -22,6 +22,7 @@ import { ChainOfThoughtStep, } from "@/components/ai-elements/chain-of-thought"; import { Button } from "@/components/ui/button"; +import { languageOfStreamingArtifact } from "@/core/artifacts/streaming-write-preview"; import { cn } from "@/lib/utils"; import { getStepDisplay, @@ -177,13 +178,17 @@ function ToolStep({ const display = getStepDisplay(step.key, step.label, step.args); const argNode = renderStepArgs(step.key, step.args, resolveAgentName); const [, toolName] = step.key.split(":"); - // 只让「自己生成/展示的文件」可点(write_file / str_replace / present_files), - // 与主聊天页一致。read_file 不可点 —— 否则智能体调用技能时读取的 SOUL.md、 - // 执行的 .py 脚本等也会被渲染成可点击文件名,点开却没有意义。 + // 只让「自己生成/展示的文件」可点,与主聊天页一致。read_file 不可点 —— 否则智能体 + // 调用技能时读取的 SOUL.md、执行的 .py 脚本等也会被渲染成可点击文件名,点开却没有意义。 + // write_file / str_replace 还要过与文件卡同一道门槛(`languageOfStreamingArtifact`, + // 只认 .md/.html/.mermaid 等可预览成品):席位写的过程文件(fetch.py / r1.txt)与 + // 畸形路径(mnt/user-data/outputs)只作步骤展示、点了也不会打开沙箱。 + // present_files 由后端校验"outputs 下真实存在",保持可点。 + const stepPath = typeof step.args?.path === "string" ? step.args.path : ""; const isArtifactStep = - toolName === "write_file" || - toolName === "str_replace" || - toolName === "present_files"; + toolName === "present_files" || + ((toolName === "write_file" || toolName === "str_replace") && + !!languageOfStreamingArtifact(stepPath)); return ( )} -