From fdade39c61ca7aa8d60d325bd91cbbe92ad2bbe6 Mon Sep 17 00:00:00 2001 From: ddcat666 <26564566+ddcat666@users.noreply.github.com> Date: Sun, 27 Sep 2026 08:23:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(database):=20=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=20-=20=E5=AF=B9=E9=BD=90=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=92=8C=E5=B9=B6=E5=90=8C=E6=AD=A5=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/database/migrations.go | 2 +- docs/content/docs/backend/backend-database.mdx | 9 ++++++--- docs/content/docs/backend/http-api.mdx | 15 +++++++++++++++ docs/content/docs/overview/features.mdx | 8 ++++++++ docs/content/docs/progress/pending-test.mdx | 17 ++++++++++++++++- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/backend/internal/database/migrations.go b/backend/internal/database/migrations.go index c3988fd9c..d0f201d34 100644 --- a/backend/internal/database/migrations.go +++ b/backend/internal/database/migrations.go @@ -27,7 +27,7 @@ const cloudAgentGeminiCacheChecksum = "sha256:cloud-agent-gemini-cache-v36-20260 const cloudAgentGeminiCacheIdentityChecksum = "sha256:cloud-agent-gemini-cache-identity-v37-20260925" const prefixedIDSequenceReconcileChecksum = "sha256:prefixed-id-sequence-reconcile-v38-20260926" const skillLibraryCategoriesChecksum = "sha256:skill-library-categories-v39-20260926" -const builtinSkillTombstonesChecksum = "sha256:builtin-skill-tombstones-v40-20260926" +const builtinSkillTombstonesChecksum = "sha256:builtin-skill-tombstones-v40-20260927" const postgresSchemaMigrationLockID int64 = 73123910420260830 diff --git a/docs/content/docs/backend/backend-database.mdx b/docs/content/docs/backend/backend-database.mdx index bda833e8e..c8445beee 100644 --- a/docs/content/docs/backend/backend-database.mdx +++ b/docs/content/docs/backend/backend-database.mdx @@ -19,11 +19,11 @@ description: 影策后端核心持久化表与状态边界 ## 结构迁移与版本 -当前结构版本为 38。版本 38 `prefixed_id_sequence_reconcile` 创建(若缺失)并校准 `id_sequences`:`CHANNEL`、`MODEL`、`PTIER`、`ATTEMPT`、`LMODEL`、`REVISION`、`ROUTE` 按对应业务表的最大有效 ID 前移,包含软删除记录,不回退已有序列、不重写业务 ID。分配新 ID 时再次校准并检查冲突;SQLite → PostgreSQL 迁移完成后也校准序列。 +当前结构版本为 40。版本 40 `builtin_skill_tombstones` 新增内置技能删除记录,管理员删除平台技能后,后续启动同步不会重新创建该技能;版本 39 `skill_library_categories` 新增 `skill_library_categories` 表,并为 `user_skill_states` 增加 `library_category_id`,保存个人技能库分类及每个用户对技能的归类;分类不改变 `skills.tag` 的技能广场共享分类。版本 38 `prefixed_id_sequence_reconcile` 创建(若缺失)并校准 `id_sequences`:`CHANNEL`、`MODEL`、`PTIER`、`ATTEMPT`、`LMODEL`、`REVISION`、`ROUTE` 按对应业务表的最大有效 ID 前移,包含软删除记录,不回退已有序列、不重写业务 ID。分配新 ID 时再次校准并检查冲突;SQLite → PostgreSQL 迁移完成后也校准序列。 版本 36 `cloud_agent_gemini_cache` 创建 `cloud_agent_gemini_caches`,保存用户范围内的官方 Gemini 缓存元数据;版本 37 `cloud_agent_gemini_cache_identity` 将缓存标识约束修正为 `(user_id, cache_key)`,移除旧的全局 cache_key 唯一索引。版本 35 `auth_notifications` 为认证通知与组合验证补齐 `auth_verifications`、`notification_quotas`、`sms_channels`、`sms_records` 四张表,并为 `users` 增加 `phone`、`email_verified_at`、`phone_verified_at`,为 `email_verification_codes` 增加 `attempts`;同时创建非空手机号唯一索引。版本 34 `task_media_recovery` 为 `tasks` 增加 `media_recovery_json`(text)和 `media_stage`(最长 24 字)。版本 33 `oauth_state_accepted_terms` 为 `o_auth_states` 增加非空布尔列 `accepted_terms`,默认 `false`,不替历史流程补造同意记录。 -升级前备份,按既有流程执行 `migrate-schema up` 和 `verify` 后再启动新后端。旧版本二进制不支持版本 38,回退需恢复匹配的数据库备份,并评估备份之后的新写入;不能只切回旧镜像。关闭自动迁移的生产环境必须运行正式迁移;手工改表不能更新 `schema_migrations` 的版本与校验和记录。 +升级前备份,按既有流程执行 `migrate-schema up` 和 `verify` 后再启动新后端。旧版本二进制不支持版本 40,回退需恢复匹配的数据库备份,并评估备份之后的新写入;不能只切回旧镜像。关闭自动迁移的生产环境必须运行正式迁移;手工改表不能更新 `schema_migrations` 的版本与校验和记录。 ### 生成成功后的作品保存恢复 @@ -137,7 +137,10 @@ docker compose -f docker-compose.deploy.yml up -d backend web | `skills` | 保存技能公开元数据、当前版本指针、来源和 GitHub 同步状态 | `instruction` 仅保留入口 `SKILL.md` 的兼容投影;目录文件不展开写入该字段 | | `skill_versions` | 保存每次安装、编辑或同步形成的不可变技能版本 | 记录内容哈希、入口路径、规范化 ZIP 的存储键、文件数、总大小和 GitHub commit | | `skill_files` | 保存某个版本的文件索引 | `(skill_version_id, path)` 唯一;只保存路径、类型、MIME、大小和 SHA-256,不保存正文 | -| `user_skill_states` | 保存用户的加入、收藏、安装版本和自动更新选择 | 技能正文读取仍经过公开性和归属校验,不能通过文件接口绕过私有技能权限 | +| `skill_library_categories` | 保存个人技能库分类和管理员创建的平台分类 | personal 分类按用户隔离;platform 分类对所有用户可见;分类名在用户可见范围内唯一,删除分类只清除归类引用 | +| `user_skill_states` | 保存用户的加入、收藏、安装版本、自动更新选择及该用户对技能的技能库分类 | `library_category_id` 属于用户技能库元数据,不修改 `skills.tag` 等技能广场共享分类;技能正文读取仍经过公开性和归属校验 | + +技能库分类由 schema migration 39 创建/扩展;内置技能删除记录由 schema migration 40 创建。删除分类时在事务内清空对应 `user_skill_states.library_category_id` 后删除分类记录,不会级联删除任何技能。删除内置技能时写入 tombstone,后续启动同步会跳过该技能。 规范化技能包保存在后端数据目录的 `skill-packages//.zip`,数据库只保存索引和版本指针。上传 ZIP 时强制校验 `SKILL.md`、路径越界、软链接、重复路径、文件数量和解压大小;GitHub 技能保存公开仓库、分支、子目录和提交 SHA,后台每 6 小时检查一次开启自动更新的技能,并记录最近检查、同步时间及失败状态。 diff --git a/docs/content/docs/backend/http-api.mdx b/docs/content/docs/backend/http-api.mdx index 011e966b9..6d1fbe1ef 100644 --- a/docs/content/docs/backend/http-api.mdx +++ b/docs/content/docs/backend/http-api.mdx @@ -339,6 +339,21 @@ CSV 使用中文表头、UTF-8 BOM、CRLF;金额按整数分精确转换为两 常量:后端 `service/error_codes.go`,前端 `web/src/services/api/error-codes.ts`。 +## 技能库分类 API + +以下接口需要登录。技能库分类与技能广场共享分类分离:`skills.tag` 仍表示共享市场分类;用户技能库分类记录在用户自己的技能状态中,只影响该用户技能库和画布 Agent。 + +| 方法 | 路径 | 行为 | +| --- | --- | --- | +| GET | `/api/skills/library-categories?scope=mine\|created` | 返回当前用户可见的个人分类和平台分类,以及所选视图下每类数量、全部技能数和未分类数量。`mine` 包含自己创建及已加入的公开技能;`created` 只统计自己创建的技能。 | +| POST | `/api/skills/library-categories` | 请求 `{ "name": "分镜", "scope": "personal" }`。`scope` 可省略并默认为 `personal`;管理员可指定 `platform`,该分类对所有用户可见、可分配和筛选。同一用户可见范围内分类名唯一。 | +| DELETE | `/api/skills/library-categories/:id` | 删除个人分类(仅分类所有者)或平台分类(仅管理员),只解除该分类与技能的关联,不删除技能。 | +| PATCH | `/api/skills/:id/library-category` | 请求 `{ "categoryId": "分类 ID" }` 设置分类;空字符串清除分类。仅允许对自己创建或已加入的技能操作,并且只能使用当前用户的个人分类或平台分类。 | + +`GET /api/skills` 可带 `libraryCategoryId` 或 `libraryUncategorized=true`,仅用于 `scope=mine` / `scope=created`,且两者不能同时使用。它们可与共享分类筛选 `tag` 同时提供,结果需同时满足两个筛选条件。分类列表的数量不受搜索词影响,表示对应技能库范围内的完整数量。 + +技能列表响应中的 `categories` 是技能广场共享分类,包含 `value`、`label` 和 `count`;`count` 统计已启用且公开的技能,不受当前搜索词、分页和视图筛选影响。它与技能库个人/平台分类是两套独立分类。 + ## 画布工具 API 以下接口均要求登录,使用标准业务信封: diff --git a/docs/content/docs/overview/features.mdx b/docs/content/docs/overview/features.mdx index 3c75f618c..1b00bc4cb 100644 --- a/docs/content/docs/overview/features.mdx +++ b/docs/content/docs/overview/features.mdx @@ -87,6 +87,14 @@ description: 当前项目已实现的核心工作台能力与使用入口 云端画布 Agent 已分离行为策略、用户目标、参考事实和运行状态。续聊保留已送达插话,不再继承代码预设的创作自由;旧待办只作上下文,可移除取消项,催办不会强制工具调用或无限重复。提示词来源与发布约束见[画布 Agent 提示词与用户意图](/docs/backend/agent-prompt-policy),真实模型行为仍待场景验收。 +## 导演台 3D-BOX 核心 MVP(待真实页面验收) + +导演台默认进入“快速镜头”工作流:演员、白模姿态、景别、运镜、当前视图设机位和预演入口集中在同一条路径;完整摆场、骨骼、动画和时间轴能力保留在“高级工作台”。“生成预演”沿用真实 Three.js 视口录制白模视频,并把产物回写为画布视频节点。画布 Agent 新增 `director_scene_read` 安全摘要读取和 `director_preview` 预演请求,后端不返回模型 URL / storage key,浏览器导演台执行实际录制。该版本是自研的 3D-BOX 核心闭环,不复制第三方实现;复杂场景编辑、Agent 语义写入和多镜头剪辑仍在后续阶段。 + +## 技能库个人分类与画布 Agent 筛选 + +技能库保留原有头部和技能广场共享分类;在“我的技能 / 我创建的”视图增加左侧个人技能库分类及技能数量。用户可为已加入或自建技能创建、分配个人分类;管理员也可创建对所有用户可见、可选、可用于筛选的分类。个人分类仅影响当前用户的技能库和画布 Agent,不改动技能广场共享分类。删除分类只解除相关归类,技能仍保留。画布 Agent 的“我的技能 / 已启用”列表可按个人或平台技能库分类快速筛选,市场页仍按共享分类浏览。 + ## 画布保存保护与版本记录 旧页面或旧缓存不能覆盖云端新内容。每次内容保存核对服务端版本,发生冲突会停止该画布自动提交并保留本地草稿;平移、缩放和打开画布不触发整份内容保存。画布顶部显示保存状态,可保留草稿后加载云端最新版。 diff --git a/docs/content/docs/progress/pending-test.mdx b/docs/content/docs/progress/pending-test.mdx index c7f1a95a0..91f41947b 100644 --- a/docs/content/docs/progress/pending-test.mdx +++ b/docs/content/docs/progress/pending-test.mdx @@ -5,11 +5,26 @@ description: 当前项目已实现功能的手工验证清单与未确认边界 # 待测试 +## 导演台 3D-BOX 核心 MVP + +- 已实现:默认快速镜头工作流、演员快速添加与落位、语义姿态/景别/运镜、当前视图设机位、真实 Three.js 白模预演视频及画布视频回写。 +- 已实现:画布 Agent 的 `director_scene_read` 安全摘要与 `director_preview` 请求桥;当前预演由已打开的浏览器导演台执行,不在后端伪造 Three.js 渲染。 +- [ ] 登录真实画布验收:快速/高级模式切换、添加演员、地面落位、姿态、景别、运镜、白模预演、视频节点回写。 +- [ ] Agent 场景验收:先读取导演场景,再请求指定镜头预演;确认只对当前画布/场景生效,确认模型 URL、storage key 等敏感字段不出现在工具结果。 +- [ ] 验收明暗主题、窄屏滚动、录制期间修改场景的快照保护、WebGL context loss 恢复;当前未启动开发服务器做真实浏览器验收。 + +## 技能库个人分类与画布 Agent 筛选 + +- 已实现:结构迁移 v39 增加用户技能库分类,v40 增加内置技能删除记录;个人分类与平台共享技能广场分类分离。管理员可创建平台分类,用户可为已加入或自建技能归类;删除分类只解除归类,删除内置技能后启动同步不会重新创建。技能库个人视图和画布 Agent 的“我的技能 / 已启用”列表均可按分类筛选。 +- [ ] 使用真实登录页面验收技能库左侧分类及数量、创建/分配/删除、未分类筛选;确认删除分类后技能仍存在,管理员平台分类对其他账号可见、可选,技能广场共享分类不变。 +- [ ] 在画布 Agent 技能选择弹窗分别验证“我的技能”和“已启用”的个人/平台分类筛选;市场页仍按共享分类筛选。 +- [ ] 在隔离 SQLite 与 PostgreSQL 数据库备份后执行 schema v39 / v40 `up` / `verify`,确认 `user_skill_states.library_category_id`、分类表和 `builtin_skill_tombstones` 迁移正确;未在生产数据库执行迁移或改写数据。 + ## 发布回归与资源引用保护 - 已修复:素材表现只在 `metadata_json` 引用资源时,批量删除和管理员资源检查仍识别该引用,不误删共享资源。已有回归覆盖共享对象、跨用户别名、事务回滚和删除队列。 - 已更新:启动并行外观加载、主题联动、统一下拉框、画布首帧与 Agent 插话的回归断言;资源消费竞态测试通过模拟 HTTP 传输验证真实持久化链路,不依赖外部网络。 -- [ ] 升级到 schema 38 前备份数据库,执行正式迁移及 verify;验证已有渠道和逻辑模型继续生成唯一可读 ID。 +- [ ] 升级到 schema 40 前备份数据库,执行正式迁移及 verify;验证已有渠道和逻辑模型继续生成唯一可读 ID,并确认内置技能删除记录不会在启动同步时被重新创建。 - [ ] 登录真实页面验收素材删除、生成结果转画布、Agent 插话、SSE 断线续传及资源访问。健康检查不能代替这些路径。 ## 注册服务协议后台配置