2.7 KiB
2.7 KiB
排错总结:/workspace/chats/new 场景下 Artifact 图片访问异常
背景
在以下 URL 场景中:
/workspace/chats/new?isnew=false&thread_id=b9a30765-0575-44c9-954e-bdaaf3d083fa&xclaw_used=true
页面会复用已有线程,并跳转到:
/workspace/chats/b9a30765-0575-44c9-954e-bdaaf3d083fa
但出现现象:
.../api/threads/b9.../artifacts/mnt/user-data/outputs/cat-generated.jpg返回Artifact not found.../api/threads/new/artifacts/mnt/user-data/outputs/cat-generated.jpg可以访问
现象与证据
本地线程目录检查结果显示:
backend/.deer-flow/threads/new/user-data/outputs/cat-generated.jpg存在backend/.deer-flow/threads/b9a30765-0575-44c9-954e-bdaaf3d083fa/user-data/outputs/不存在对应文件
这说明文件实际写入了 thread_id = "new" 的目录,而不是目标线程 b9...。
根因
问题由“线程 ID 来源不一致”触发:
- 页面层已经解析出“真实线程 ID”(query 中的
thread_id)。 - 消息渲染组件中仍直接读取路由参数
useParams().thread_id。 - 在
/workspace/chats/new下,路由参数固定是"new",导致图片/文件 URL 被拼接为/api/threads/new/artifacts/...。 - 输入与提交链路存在对
params.thread_id的兜底,存在将"new"带入写操作的风险。
修复内容
本次修复统一了线程 ID 的来源,并增加了防御性校验:
-
消息渲染链路统一使用页面透传的解析后
threadIdMessageListItem移除useParams().thread_idMessageList将threadId透传给MessageListItem
-
输入组件移除路由参数兜底
InputBox不再使用threadIdFromProps ?? params?.thread_id- 仅使用上游传入的解析后
threadId
-
提交流程增加硬保护
- 在
useThreadStream/useSubmitThread中拦截threadId === "new",阻止上传和提交继续执行
- 在
-
复用旧线程时强制路径对齐
- 在
/workspace/chats/new且命中复用条件时,立即replace到/workspace/chats/{thread_id}
- 在
涉及文件
frontend/src/components/workspace/messages/message-list-item.tsxfrontend/src/components/workspace/messages/message-list.tsxfrontend/src/components/workspace/input-box.tsxfrontend/src/core/threads/hooks.tsfrontend/src/components/workspace/chats/use-thread-chat.ts
验证结果
- TypeScript 编译检查通过:
pnpm -C frontend exec tsc --noEmit --pretty false - 逻辑上可确保后续不会再写入
threads/new/...。
影响与后续处理
本次修复不自动迁移历史文件。
已落在 threads/new/... 的旧产物,仍需要:
- 手动迁移到目标线程目录,或
- 在目标线程中重新生成。