Skip to content

Skill 完整内容提交与编辑状态 ​

状态:implemented 类型:simplification Owner:backend/yuxi/modules/extensions/skills/content.py

问题 ​

文件编辑、ZIP 替换与历史恢复各自修改有效目录并协调数据库回滚。专属 Skill 内容保存还同步撤下所有已有用户投影;前端分别维护文件、依赖和发版状态,使“保存并发版”只能保存当前局部草稿。

决策 ​

实现方案 ​

受管理 Skill 使用固定 slug 和不可变内容目录。内容提交入口先取得 Agent → Skill 资源锁,校验预期修订,再准备完整包并校验路径、根说明及依赖,最后提交当前目录引用与索引。内容提交可按请求同事务新增历史记录,记录引用该完整目录。恢复校验历史哈希与当前依赖权限后通过相同入口更新当前引用。普通 Skill 复用内容提交,历史入口只向专属 Skill 开放。内置与自建 Agent 共用绑定能力;内置 Agent 不可删除,其专属绑定持续保留,不新增解绑或重置状态。依赖索引使用用例的 owning session 读取,清理的新事务沿用调用方数据库引擎;内容用例不额外创建全局连接池。

现有 OpenAPI 的单文件、依赖和目录读写 HTTP 契约保留;本次不把前端 consumer 的迁移当作删除公开接口的授权。edit.py 仅适配文件级修订与单项变更,全部写入同一个 content.py,不保留原地写入或异常补偿机制。前端只使用整包 content 接口;文件读取仍服务预览,导出与 ZIP 导入保持原入口。这是对既有 HTTP 契约的保留,与旧数据库兼容无关。

前端为完整 Skill 保存一份编辑状态;切换文件或页签保留草稿,文件和依赖表单编辑同一根说明。文件区域或依赖区域保存全部修改,历史页发版保留已保存内容;绑定、历史与交互取舍见专属 Skill 决定。ZIP 导入与导出保留,专属编辑保留所属 Agent 导航上下文。

内容保存由运行准备物化当前内容,权限撤销继续在授权提交前撤下旧投影。当前与历史记录引用的目录不能清理,无引用目录在提交后的新资源锁内清理;文件清理在线程中执行,避免阻塞请求事件循环;清理失败只记录日志,下次提交或历史删除再次清理。执行中根说明沿用已经准备的文本,其他文件与能力授权保持现有机制。

替代方案 ​

方案取舍
keep:保留分散写入保留多套补偿流程、全用户同步与局部保存语义
narrow:只整理函数和按钮局部改善阅读,仍需协调正在使用的文件与数据库
replace:资源锁内准备完整内容、数据库提交引用统一失败边界,代价是内容目录存储与引用清理
remove:取消 ZIP、依赖或历史破坏当前已确认的用户能力,保留这些入口并复用提交

后果 ​

完整保存使用整包修订,两个修改不同文件的编辑者仍可能发生冲突;冲突保留本地草稿并要求重新加载。每次内容变更复制完整包,当前包预算保持 50 MiB 和 2000 条目。未提交或未引用目录不会影响当前内容;不承诺文件系统损坏自动恢复。版本标识保持北京时间年月日与 UUID8,历史删除不能删除仍作为当前内容的目录。

验证 ​

验证普通与专属 Skill 的原子完整保存、409 保留、发布引用、恢复、删除当前历史后的内容保留、并发写入与引用清理、数据库提交失败仍读取旧内容,以及内容保存不遍历用户投影。真实 HTTP、PostgreSQL 和 worker 回读当前内容、历史索引、投影与模型输入;前端覆盖跨文件草稿、依赖与根说明同步和统一保存。owning 文档与真实页面共同核对行为,界面证据保存在仓库外;独立 Reviewer 检查完整差异与旧补偿路径的删除。

旧能力不存在:搜索确认在线编辑、专属替换和历史恢复不再原地替换当前内容,不再通过 ORM 临时字段传递提交结果,普通内容保存不再调用全用户投影失效用例。

重新引入条件:只有新的已确认 consumer 要求独立文件级发布或全用户内容即时同步时,重新评估并记录取舍。

验收主张失败面语义 Owner直接证据 / 命令负向案例当前结果
完整保存与历史引用数据库与内容目录content.pyunit、真实 HTTP integration、worker E2E提交失败、过期基准、并发 prunePassed
一份编辑草稿多文件与依赖SkillDetailView.vue组件测试与真实页面409 保留跨文件修改Passed

本项目基于 MIT License 开源,欢迎使用和贡献。