{{ message }}
Repository navigation
Conversation
- create_folder/rename_folder 持久化前按同级目录与忽略大小写名称查重,冲突返回 409 {code: folder_name_conflict} 契约 detail,前端透传中文提示
- create_folder 补齐名称规范化(去空白、拒绝空名与路径分隔符)
- 决策记录:docs/develop-guides/decisions/implemented/2026-09-22-knowledge-folder-duplicate-guard.md(涵盖防重与创建后跳转两项决定)
创建成功后调用 openFolder 进入新文件夹,上传弹窗默认目标(= 当前浏览目录)随之切换到新文件夹。
Owner
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

变更说明
知识库同一父目录下可以创建任意多个同名文件夹:前端只校验名称非空,
KnowledgeBase.create_folder/rename_folder不查同级重名,knowledge_files表也无组合唯一约束。单层浏览 + 面包屑的交互下,同级同名文件夹完全无法区分。另外新建文件夹后视图停留在父目录,上传默认目标仍是父目录,想上传到新建文件夹需要手动再点进去。本 PR 包含两个提交:
fix(knowledge):create_folder/rename_folder持久化前通过KnowledgeFileRepository.find_folder_by_name按kb_id + parent_id + 忽略大小写的 filename在is_folder=True记录中查重,命中(重命名时排除自身)抛FolderNameConflictError;两个端点映射为 409,detail 为{"code": "folder_name_conflict", "message": ...}对象。create_folder同时补齐与rename_folder一致的名称规范化(去空白、拒绝空名与路径分隔符),其他ValueError在创建端点映射为 400(此前一律 500)。feat(web):新建文件夹成功后前端直接openFolder进入该文件夹;上传弹窗的默认目标 = 当前浏览目录(既有语义),因此新文件夹自动成为上传目标,不引入额外状态通道。bug-fix(含一个配套的前端交互改进)工程主张与 Owner
{code, message}dict detail 暴露(沿用run_busy、resume_superseded等既有 dict detail 先例)。backend/package/yuxi/knowledge/base.py(create_folder/rename_folder),查询为KnowledgeFileRepository.find_folder_by_name;commit point 为_persist_file_meta/update_fields的 PostgreSQL 写入;用户可观察面为 409 响应与前端提示。前端跳转 Owner 为web/src/components/FileTable.vue的handleCreateFolder。implemented的原因:变更小而完整、在同一 PR 中生效,替代方案(DB 唯一约束、树形展示、额外上传目标状态通道)已评估并记录在案,无待裁决的开放问题。验证情况
同级同名文件夹创建与重命名被拒绝
KnowledgeBase.create_folder/rename_folderpytest test/unit/knowledge/test_folder_name_conflict.py(4 passed,覆盖撞名不落库、大小写、空名/分隔符、rename 撞名拒绝与自身放行)pytest.raises(FolderNameConflictError)与repo.persisted == []/repo.updated == []断言同时变红冲突错误以 409 + 契约 detail 返回,异名与跨父级不受影响
knowledge_router.create_folder/rename_folder端点pytest test/integration/api/test_knowledge_router.py -k duplicate_sibling(真实 HTTP + PostgreSQL:同级创建重名含大小写变体 409 且detail.code == "folder_name_conflict"、跨父级同名 200、rename 撞名 409、rename 自身与自身大小写变体 200、正常 rename 200)TEST_USERNAME/TEST_PASSWORD,integration 用例按约定 skip,见「未验证范围」)新建文件夹后跳转进入,上传默认目标切换到新文件夹
FileTable.vue handleCreateFolder、web/src/stores/database.js enterFoldernode --test test/unit/file_upload_folder.test.js(5 passed,含新增源码契约断言);真实页面验证:在运行相同代码的部署上新建文件夹后视图跳转进入该文件夹,随后上传的文件经 PostgreSQL 任务 payload 核实携带正确parent_id并落入新文件夹refreshAfterMutation()后新增源码断言变红既有行为不回归
yuxi.knowledge.base全部子类与FileTable.vuepytest test/unit -m "not slow"864 passed(Windows 宿主机排除 106 个平台收集错误文件;63 个失败全部为 sandbox provisioner / docker-compose 契约 / nginx / CLI / symlink 类测试,在upstream/main基线上以完全相同的清单失败,属本机环境既有问题);前端pnpm run test:unit351/352 passed(唯一失败chatStartScreen.test.js在upstream/main基线同样失败,与本改动文件无交集);pnpm run lint:check通过;python scripts/verify_engineering_contracts.py通过;ruff check通过test_dify_kb.py只读 connector 拒绝 rename 用例保持绿色简化 / 删除验收
不涉及。
独立语义 Review
由不继承开发上下文的 Reviewer 审查了完整需求、全量 diff、测试与仓库规范。结论:无阻断问题。逐项核实了根目录
parent_id IS NULL情形、大小写忽略、rename 自身排除、异常映射顺序(FolderNameConflictError非ValueError子类,except 顺序正确)、前端openFolder对返回 meta 字段的依赖、enterFolder 不会误入虚拟文件夹分支。两条非阻断建议已处理或记录:集成测试补充 rename 自身大小写变体用例(已补);存量同名数据的 rename 前提与并发双写风险已写入决策记录「后果」节。未验证范围与风险
test_knowledge_router.py -k duplicate_sibling在本 PR 分支环境 skip(未配置TEST_USERNAME/TEST_PASSWORD);等价主张已由实现仓库的真实页面验证覆盖,建议在有凭据的环境补跑一次。message到达用户可见文案依赖 fix(api): 业务错误 detail 契约化与前端受控透传,恢复精准错误提示 #1053 的前端透传契约;在 fix(api): 业务错误 detail 契约化与前端受控透传,恢复精准错误提示 #1053 合并前,冲突仍被正确拒绝,仅前端提示显示为 409 公共文案("请求冲突,请刷新后重试")。功能独立成立。事故反馈
未达到 postmortem 门槛:同级同名文件夹不产生数据丢失或错误索引,仅是 UI 无法区分;已落地 guard 与负向测试。
界面变更
新建文件夹成功后视图跳转进入该文件夹(面包屑追加一级);同名冲突时弹出中文错误提示。截图可在需要时补充。
关联事项
相关讨论:#617(创建/上传位置的易用性,maintainer 确认的 VS Code 式当前目录语义——本 PR 沿用"当前浏览目录即操作上下文"模型,将创建与进入合并为一步)。
补充说明
兼容性:历史同名文件夹数据不受影响;
create_folder新增的名称规范化与rename_folder既有规则一致。无配置与迁移。