Merge remote-tracking branch 'origin/master' into editor-agent-refactored

# Conflicts:
#	docs/README.md
#	src/components/image-editor/EditorAgentConversation/EditorAgentConversationPanelView.tsx
#	src/components/image-editor/EditorAgentConversation/useEditorAgentConversation.ts
#	src/components/image-editor/EditorAgentConversationPanelView.test.tsx
#	src/components/image-editor/ImageCanvasStageView.tsx
This commit is contained in:
2026-07-17 17:32:08 +08:00
272 changed files with 1697 additions and 1300 deletions
@@ -4229,3 +4229,9 @@
- 就绪边界:HTTP `/readyz` 同时验证调用池握手和缓存读连接;required subscription 失败必须不就绪。非 HTTP worker / controller 不创建缓存读连接,继续使用 1 条调用连接和各自的队列窄订阅。
- 运维口径:`GENARRATIVE_SPACETIME_POOL_SIZE=8` 表示 8 条调用连接,HTTP 基础拓扑另加 1 条缓存读连接;外部生成和充值过期监听的独立窄订阅不计入该值。读模型行缓存从 8 份降为 1 份,但 SDK 空 table metadata、8 条调用 socket 和 runner 仍存在,不承诺总 RSS 等比例降为八分之一。
- 验证方式:`cargo test -p spacetime-client --manifest-path server-rs/Cargo.toml --lib``cargo check -p api-server --manifest-path server-rs/Cargo.toml``npm run check:encoding``git diff --check`;发布后在 8 个调用槽暖机后对比 api-server cgroup memory / PSS,并确认 `/readyz` 与代表性 gallery、公开详情、创作入口和用户标签读取正常。
## 2026-07-17 旧创作模板与入口停止维护
- 决策:旧创作模板、旧创作入口及其专属运行服务进入下线范围,不再为跳一跳、抓大鹅 Match3D、儿童动作 Demo 等旧链路修复兼容问题、补生成脚本或维持专属门禁。
- 边界:共享账号、钱包、资产、图片编辑器、公开作品、通用 HostBridge、API、SpacetimeDB、发布运维和安全能力不属于旧链路,仍需维持正式门禁。历史文档只作为背景材料,不再作为旧入口继续运行的依据。
- 清理方式:允许直接删除已经失效的旧素材生成命令、入口路由、专属服务和对应测试;删除工程链路时仍需核对是否被当前共享能力引用,不能连带移除仍在使用的公共契约或持久化事实。
+15 -15
View File
@@ -240,21 +240,21 @@
- 验证:`npm run test -- src/components/image-editor/ImageCanvasEditorModel.test.ts src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx --reporter verbose`
- 关联:`src/components/image-editor/ImageCanvasEditorModel.ts``src/components/image-editor/ImageCanvasPublicationMaterialsDemoPanelView.tsx``src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`
## 图片画布快速编辑不要直接提交普通图片 URL
## 图片画布生成请求不要直接提交临时媒体源
- 现象:图片画布快速编辑站内示例图、历史 generated 图或 OSS generated 图时,后端返回 `修改图片参考图必须是图片 Data URL。`
- 原因:快速编辑直接把图层 `src` 塞进 `/api/editor/images/generations``referenceImageSrcs`;默认示例图和部分持久化图层的 `src``/creation-type-references/*.webp``/generated-*` 或 OSS URL,而 `api-server` 的编辑参考图解析只接收 `data:image/*;base64,...`
- 处理:前端统一通过 `resolveEditorImageReferenceDataUrl(...)` 在提交前读取图片字节并转成图片 Data URL;Data URL 原样透传,`/generated-*` 和 generated OSS URL 先走 `/api/assets/read-url` 换签后由浏览器直读 OSS,直读失败时才 fallback 到 `/api/assets/read-bytes`,普通 public 路径直接 fetch
- 验证:`npm run test -- src/services/image-editor/editorImageReference.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx -t "editorImageReference|converts non-data-url quick edit source images before submitting references"`
- 关联:`src/services/image-editor/editorImageReference.ts``src/components/image-editor/ImageCanvasEditorView.tsx``docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`
- 现象:图片画布快速编辑、参考生成、去背景或角色动画提交 Data URL / Blob URL 时,前端或后端返回“必须先上传 OSS”
- 原因:Data URL / Blob URL 体积大且不能作为持久引用;如果写入外部生成队列,请求体会膨胀,worker 也无法稳定复用浏览器临时资源
- 处理:提交前优先复用图层已有 `objectKey`、项目资源 ID 或素材 ID;未登记的本地图片和普通 public 图片路径先通过 `resolveEditorGenerationMediaReference(...)` 读取并上传 OSS,再把稳定引用交给生成接口。Data URL 只允许用于浏览器内压缩、标注等临时处理,不能进入 API 请求、队列载荷或项目持久化
- 验证:`npm run test -- src/services/image-editor/editorProjectClient.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx``cargo test -p api-server inline_data_url --manifest-path server-rs/Cargo.toml`
- 关联:`src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts``src/services/image-editor/editorProjectClient.ts``server-rs/crates/api-server/src/editor_generation_queue.rs``docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`
## 图片编辑器角色动画不要默认提交大图 Data URL
## 图片编辑器角色动画必须提交稳定图片引用
- 现象:图片编辑器里对角色图点击 `生成动画` 后,后端返回 `Failed to buffer the request body: length limit exceeded`,请求还没进入角色动画 handler
- 原因:角色动画生成请求曾把角色图片 `src` 原样作为 `sourceImageSrc` 放进 JSON;角色图如果是较大的 Data URL,会超过 Axum 默认 `2MB` body limit,在 `Json` 提取器阶段被拦截
- 处理:前端在角色图已持久化时优先提交 `objectKey`,只把 Data URL 作为未持久化本地临时图兜底;后端 `/api/editor/character-animations/generations` 单独配置 `12MB` body limit 兼容旧请求,但新链路不应依赖传大图 JSON
- 验证:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx -t "only exposes character animation"``cargo test -p api-server editor_character_animation_accepts_character_image_body_above_default_limit --manifest-path server-rs/Cargo.toml`
- 关联:`src/components/image-editor/ImageCanvasEditorView.tsx``server-rs/crates/api-server/src/modules/play_flow.rs``server-rs/crates/api-server/src/app.rs``docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`
- 现象:图片编辑器里对尚未上传的角色图点击 `生成动画` 后,前端或后端返回 `sourceImageSrc 必须先上传 OSS`
- 原因:角色动画会进入外部生成队列,浏览器 Data URL / Blob URL 既不适合持久任务,也会放大 JSON 请求体
- 处理:前端统一通过 `resolveEditorGenerationMediaReference(...)` 取得 `objectKey` 或画板资源引用;本地临时角色图必须先上传 OSS。后端在入队前同步拒绝内联媒体,不再通过放宽 body limit 兼容 Data URL
- 验证:`npm run test -- src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx``cargo test -p api-server editor_character_animation --manifest-path server-rs/Cargo.toml`
- 关联:`src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts``server-rs/crates/api-server/src/character_animation_assets.rs``server-rs/crates/api-server/src/app.rs``docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`
## 图片编辑器角色动画抽帧不要采到视频尾点
@@ -328,11 +328,11 @@
- 验证:`npm run test -- src/services/assetReadUrlService.test.ts --reporter verbose` 应覆盖大量不同 objectKey 同时换签时首批限量放行、后续按间隔派发;发布现场同类页面刷新时,Nginx `GET /api/assets/read-url` 429 应从 `upstream_status=-` / `genarrative_api_rps` 收敛。
- 关联:`src/services/assetReadUrlService.ts``src/hooks/useResolvedAssetReadUrl.ts``src/components/ResolvedAssetImage.tsx``docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`
## 图片编辑器 Seedance 2.0 参考媒体不要提交视频 Data URL
## 图片编辑器 Seedance 2.0 参考媒体只提交稳定引用
- 现象:画板生成视频选择 Seedance 2.0 并上传参考视频后,请求体暴涨、可能返回 `413` 或上游拒绝 `video_url.url`;文档示例或测试如果写 `data:video/mp4;base64,...`,后续实现很容易照抄。
- 原因:火山 Seedance 2.0 参考视频只支持公网 URL 或 `asset://` 素材 ID,项目内画板资源应以 `objectKey` 由后端换签;视频不支持 Base64 / `data:video`,且 50MB 视频转 Base64 后会逼近或超过 64MB 请求体上限。参考音频虽然支持 Base64,但也不能单独输入,且大文件同样不应塞进 JSON
- 处理:参考视频 / 音频上传先走 `/api/assets/direct-upload-tickets` 直传 OSS,再 `/api/assets/objects/confirm` 确认;前端保留 signed URL 做预览,提交生成时优先使用 `objectKey`。后端归一化必须拒绝 `data:video/*`,非 Seedance 模型携带参考字段也必须拒绝;Ark body 显式带 `generate_audio:false`
- 原因:画板生成会进入持久队列,Base64 / Data URL / Blob URL 会放大请求和任务 JSON;直接签名客户端给出的 objectKey 又会绕过跨账号素材归属校验。项目资源 ID、素材 ID 和 objectKey 必须先解析到当前 owner 的正式对象,公网 URL 与 `asset://` 才能按供应商契约直接透传
- 处理:本地参考图片 / 视频 / 音频先走 `/api/assets/direct-upload-tickets` 直传 OSS,再 `/api/assets/objects/confirm` 确认;前端保留 signed URL 做预览,提交生成时使用 `objectKey`、项目资源 ID 或素材 ID。后端归一化拒绝全部 `data:*` / `blob:*`,签名 OSS URL 前统一校验 owner;稳定引用字段总长度限制为 `256KB`,非 Seedance 模型携带参考字段也必须拒绝;Ark body 显式带 `generate_audio:false`
- 验证:`npx vitest run src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/services/image-editor/editorReferenceUploadClient.test.ts --reporter verbose``cargo test -p api-server editor_video --manifest-path server-rs/Cargo.toml``cargo test -p shared-contracts editor_video_request_supports_seedance_multimodal_references --manifest-path server-rs/Cargo.toml`
- 关联:`src/services/image-editor/editorReferenceUploadClient.ts``src/components/image-editor/useImageCanvasUploadWorkflow.ts``src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts``server-rs/crates/api-server/src/character_animation_assets.rs``docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`