Merge branch 'master' into feat/artagent-artifact-jump-to-focus
Project CI / Repository checks (pull_request) Successful in 45s
Project CI / Frontend tests (pull_request) Successful in 3m48s
Project CI / Backend tests (pull_request) Successful in 4m25s
Project CI / Native shell tests (pull_request) Successful in 11m50s

This commit is contained in:
2026-07-31 16:48:05 +08:00
29 changed files with 1839 additions and 215 deletions
@@ -3,7 +3,7 @@
"info": {
"title": "陶泥儿外部编辑器 OpenAPI",
"version": "1.0.0",
"description": "外部系统调用陶泥儿图片画布项目、画布布局、素材库,以及图片、视频、音效、音乐等编辑器素材生成/编辑能力的 v1 契约。新建 projectId 使用 proj- 前缀,新建 taskId / operationId 使用 task- 前缀;历史 editor-project-*、aitask_*、extgen-* ID 仍可作为既有资源标识传入。"
"description": "外部系统调用陶泥儿图片画布项目、画布布局、素材库,以及图片、视频、音效、音乐等编辑器素材生成/编辑能力的 v1 契约。新建 projectId 使用 proj- 前缀,新建 taskId / operationId 使用 task- 前缀;历史 editor-project-*、aitask_*、extgen-* ID 仍可作为既有资源标识传入。\n\n兼容性说明:v1 当前处于无外部存量调用方阶段,正式对外发放 API Key 之前,契约可能在不升 info.version、不设弃用期的情况下发生包含字段移除在内的破坏性变更。生成客户端时请勿假定本文档已冻结。"
},
"servers": [
{
@@ -2293,12 +2293,6 @@
"null"
]
},
"provider": {
"type": [
"string",
"null"
]
},
"taskId": {
"type": [
"string",
@@ -2476,12 +2470,6 @@
"null"
]
},
"provider": {
"type": [
"string",
"null"
]
},
"taskId": {
"type": [
"string",
@@ -2852,7 +2840,6 @@
"sourceType",
"prompt",
"model",
"provider",
"taskId"
],
"properties": {
@@ -2895,9 +2882,6 @@
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"taskId": {
"type": "string"
},
@@ -3231,7 +3215,6 @@
"spritesheetHeight",
"prompt",
"model",
"provider",
"taskId",
"priceMudPoints"
],
@@ -3277,9 +3260,6 @@
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"taskId": {
"type": "string"
},
@@ -3718,7 +3698,6 @@
"sourceType",
"prompt",
"model",
"provider",
"taskId",
"durationSeconds",
"resolution",
@@ -3767,9 +3746,6 @@
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"taskId": {
"type": "string"
},
@@ -3955,7 +3931,6 @@
"sourceType",
"prompt",
"model",
"provider",
"taskId",
"priceMudPoints",
"audioKind"
@@ -4003,9 +3978,6 @@
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"taskId": {
"type": "string"
},
@@ -16,6 +16,56 @@
---
## 2026-07-30 抠图实际后端作为 generationInputs 顶层内部元数据保存
- 背景:角色、图标图集和 UI 图集抠图派生资产需要保留最终实际执行的处理后端,供后台诊断 BgFilter、阿里云通用抠图和本地键色的降级结果;把抠图模型写成 `generationInputs.fields` 的“处理模型”会进入图片信息,与用户可见输入快照语义冲突,而覆盖正式资产 `model` 又会丢失源生图模型。
- 决策:继续使用现有 `generation_inputs_json` JSON 包络,不修改 SpacetimeDB schema。`fields` / `references` 只保存用户可见生成输入;仿照顶层 `screenColorHex`,抠图派生资产在顶层写入 `mattingProvider` / `mattingModel`。BgFilter 记录本次实际 `seg_model`;阿里云记录 `Aliyun Matting / segment-common-image`;本地键色记录 `Genarrative Local / screen-color-keying`。三条链路的正式资产 `model` 继续继承源生图模型,图片信息不读取顶层内部字段。`screenColorHex`、`mattingProvider`、`mattingModel` 和素材顶层 `provider` 属于内部执行信息:普通用户(包括素材 owner)、精选提交 / 点赞响应与匿名公开读取统一省略,只有后台管理和服务端 raw 审计读取原始值;历史数据不迁移,在 User/Public mapper 边界清理。角色动作逐帧可能混用多个 fallback,本次不把单帧结果提升为整组动画模型。
- 影响范围:`server-rs/crates/api-server/src/editor_project.rs` 的抠图结果和角色 / 图标 / UI 派生资产持久化、图片信息兼容测试、后端数据契约与图片画布 MVP 文档;不修改前端生产展示逻辑、请求 DTO、SpacetimeDB 表、迁移或生成绑定。
- 验证方式:后端单测覆盖三种实际结果映射、顶层元数据不改写 `fields`,结构断言覆盖三条派生资产持久化链路仍保留源生图模型;User/Public mapper 测试同时证明素材 owner、精选提交 / 点赞与匿名响应均省略 `provider` 和三个内部键,Admin raw payload 保留原始值;前端测试覆盖顶层字段不在图片信息或搜索索引出现。运行 `cargo test -p api-server editor_project::tests --manifest-path server-rs/Cargo.toml`、图片信息定向前端测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。
- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
---
## 2026-07-31 修正抠图内部元数据的普通用户读取边界
- 背景:2026-07-30 的记录误把素材 owner 与后台审计并列为原始抠图执行信息的读取方。owner 是普通用户,前端不展示字段不能阻止其从项目资源、素材库、精选提交 / 点赞回包、画布布局或任务完成响应的网络 payload 读取 BgFilter、阿里云、本地键色、具体分割模型或背景色。
- 决策:本条取代 2026-07-30 决策中“素材 owner、精选提交响应仍可读取原始值”的表述。普通用户(包括素材 owner)和匿名公开读取必须共同过滤素材顶层 `provider`、内部处理 `model`,以及 `generationInputs` 顶层 `screenColorHex`、`mattingProvider`、`mattingModel`;正常用户可见生成 `model` 和其他合法功能性顶层字段(例如 `characterAnimation`)保持不变。User/Owner mapper 先完成该清理,public mapper 在其基础上叠加公开字段规则;后台管理与服务端审计继续使用 raw mapper 和持久化原值。历史数据不迁移,统一在读取边界清理。
- 入站与持久化:客户端提交的 `generationInputs` 不得伪造上述内部键,服务端在实际处理完成后才写入可信值。手动去背景的正式素材 `model` 必须继承经服务端验证的正常源生图模型;若来源或祖先链不存在正常模型则为 `null`,不得写入 `BgFilter complex` 等内部处理模型。内部抠图 provider / model 可继续持久化供后台审计,普通用户完成响应和用户可见错误文本均不得暴露它们;手动去背景与角色动作透明化失败在 Owner HTTP / 任务状态边界统一替换为稳定业务文案,原始错误只留在任务记录、tracing 和后台审计。
- 影响范围:项目资源、素材库、精选提交 / 点赞、图片 / 图标 / 视频 / 音频 / 角色动画生成完成、Agent 紧凑结果和识别出的画布资源 / 图层快照的 User/Public mapper;手动去背景持久化和完成响应;External Editor API 创建素材 / 资源时的保留键入站清理;相应响应 / OpenAPI 契约、前端搜索 / 详情 / ZIP 过滤测试与后台 raw 审计测试。同源画布 BFF 的角色、图标和 UI 请求继续由前端自动提交默认 `segModel=birefnet`,后端继续校验并在缺失时回落默认值;该请求控制字段不进入 `generationInputs`、普通用户响应、搜索、详情、导出或错误详情。角色动作的 `seg_model` 继续由后端固定。不修改 SpacetimeDB schema、迁移或 bindings。
- 验证方式:Owner 和匿名响应覆盖无 `provider`、无内部 `model`、无三个内部 `generationInputs` 键,且正常 `model` 与 `characterAnimation` 仍保留;Admin raw payload 保持完整。覆盖历史 `BgFilter complex`、三类入站伪造键、手动去背景源模型回溯和用户错误文本过滤;运行 api-server 定向测试、前端定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding` 与 `git diff --check`。
- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
---
## 2026-07-31 接受外部 OpenAPI v1 的未版本化 breaking change
- 背景:2026-07-31「修正抠图内部元数据的普通用户读取边界」把 OpenAPI 更新列为影响范围内的机械同步,但实际动作是从已发布的 `/api/external/v1` 契约中删除四个生成响应里原本 `required` 的 `provider`,另从 `EditorProjectResource` / `EditorAsset` 删除可选 `provider`,而 `info.version` 仍为 `1.0.0`、路径前缀未变。严格反序列化或由 OpenAPI 生成的调用方会在服务端上线瞬间直接失败,且不需要调用方做任何动作。脱敏目标本身成立,但契约处理方式当时没有单独定性。
- 决策:确认这是 breaking change 而非文档同步,并接受本次不升版本、不提供兼容字段、不设弃用期。唯一依据是截至 2026-07-31 `external_api_key` 无属于外部第三方的存量调用方。该豁免不具一般性:API Key 由用户在个人中心自助发放,`/api/external/v1/openapi.json` 又是该批路由中唯一免鉴权端点,因此「无外部调用方」不是受控状态,出现非内部账号活跃密钥、对外公布契约或与外部团队联调后立即失效。今后删除响应字段、把字段移出 `required`、收窄类型或取值、改变字段语义、新增请求必填字段均视为 breaking,存量调用方出现后必须按兼容值、弃用期或 `/api/external/v2` 三选一处理,只更新 JSON 不构成合规变更流程。本次不追加代码改动。
- 影响范围:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md` 新增「版本与兼容策略」一节;`docs/openapi/genarrative-external-v1.openapi.json` 的 `info.description` 补充面向集成方的兼容性说明;`pitfalls.md` 记录「无调用方」不可当长期前提。不修改响应结构、请求 DTO、路由或 `external_editor_api.rs` 断言。
- 验证方式:`info.version` 保持 `1.0.0` 且 JSON 仍可被 `serde_json` / `json.load` 解析;`external_editor_api.rs` 既有 openapi 断言继续通过。该断言只校验 schema 形状、不校验兼容性,因此通过不等于契约安全,判定仍以上述 breaking 清单为准。正式对外发放第一个外部密钥前需复核本条是否仍成立。
- 关联文档:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`、`docs/openapi/genarrative-external-v1.openapi.json`、`docs/project-memory/shared-memory/pitfalls.md`。
---
## 2026-07-31 历史素材的内部处理模型不做回溯清理
- 背景:用户可见性过滤 `isEditorUserVisibleGenerationInputField` 的实现是标题精确匹配 `处理模型`,既不识别语义也不探测取值;服务端 User/Public mapper 只清理 `generationInputs` 顶层的 `screenColorHex` / `mattingProvider` / `mattingModel`,不遍历 `fields` 数组。历史资产中存在标题为「抠图模型」、取值形如 `动漫风格 anime-seg` 的字段,两侧都拦不住,因此仍会出现在图片信息弹窗和画布 ZIP 导出元数据中。MVP 接入方案原文「前端同时过滤历史项目中已持久化的处理模型字段」读起来是全覆盖保证,与实际实现和历史数据存在显式冲突。
- 决策:维持产品决策——历史素材不迁移、不回溯清理,本次不扩大过滤范围,不修改 `isEditorUserVisibleGenerationInputField`。改为收敛文档口径:明确过滤是标题精确匹配而非语义识别,明确「抠图模型」为已知例外且属于接受状态,不得据此判定为缺陷。约束只对新写入生效,新产生的 `generationInputs.fields` 不得再写入任何内部处理模型字段,无论标题为何。若将来决定扩大过滤范围,必须先对生产 `generation_inputs_json` 做标题去重查询枚举真实存在的历史标题,不得仅凭测试夹具推断清单。
- 影响范围:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md` 收敛该句表述并补充已知例外;`pitfalls.md` 记录过滤口径与排查方式。不修改前端过滤实现、服务端 mapper、素材数据或导出结构。
- 验证方式:图片信息弹窗与画布 ZIP 共用同一过滤口径,任何一侧改动必须同时覆盖另一侧;既有 `ImageCanvasMetadataModalView` 与 `ImageCanvasExportModel` 测试保持通过,不新增针对历史「抠图模型」的过滤断言,以免与本决策冲突。
- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/project-memory/shared-memory/pitfalls.md`。
---
## 2026-07-30 图片画布搜索不得索引内部模型和 Provider
- 背景:素材和图层详情虽已把内部处理模型显示为 `-`,搜索仍索引原始 `model` 与 `provider`,导致 `BgFilter complex`、`segment-common-image`、`BgFilter` 或 `Aliyun Matting` 等隐藏信息可被查询命中,并出现“命中但无可见匹配字段”的异常体验。
- 决策:素材与图层搜索只索引用户可见生成模型;统一复用 `isEditorInternalProcessingModel(...)` 排除内部处理模型,并完全排除 `provider`。该规则只约束前端临时搜索值,不删除或改写素材、图层及后端保存的原始审计字段;`gpt-image-2`、`audio1.0` 等正常模型继续支持搜索。
- 影响范围:`ImageCanvasAssetLibraryModel.ts` 的素材与图层搜索值、图片画布素材 / 图层侧栏搜索和对应前端架构文档;不改变持久化、详情展示、删除、移动或画布保存行为。
- 验证方式:模型单测覆盖内部模型和 Provider 不命中、正常模型继续命中且原对象元数据不变;侧栏交互测试覆盖素材与图层两类入口。运行对应 Vitest、`npm run typecheck`、`npm run lint:eslint`、`npm run check:encoding` 和 `git diff --check`。
- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
---
## 2026-07-31 每日免费泥点基础额度纳入后台钱包配置
- 背景:每日免费泥点已是独立余额桶,但基础发放量仍在运行时固定为 `20`,后台“账号配置”只能维护注册初始泥点,运营调整需要改代码。
@@ -35,7 +85,6 @@
- 影响范围:`scripts/deploy/production-stdb-publish.sh`、`scripts/database-backup-to-oss.mjs`、生产运维门禁和本文档。
- 验证方式:`npm run check:database-backup`、`npm run check:production-ops`、`npm run check:encoding`、`git diff --check`;dev 现场还必须确认 transient unit 不在 Jenkins session scope,旧 deferred 归档逐份变为 OSS 已验真对象后被删除,备份锁清空,核心服务与公开接口健康。
- 关联文档:`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
---
## 2026-07-31 画布 Agent 图片结果单击直接定位
+17 -1
View File
@@ -260,7 +260,7 @@
- 现象:画板生成、快速编辑、图标素材或 UI 素材提取如果允许直接提交 generated objectKey,用户只要知道其他账号的私有 objectKey,就可能让 api-server 签名读取并送给外部生成供应商。
- 原因:Data URL/Blob URL 只允许停留在浏览器临时态,正式编辑器引用必须先上传并经统一 resolver 校验归属。
- 处理:所有私有对象引用在读取字节或签发 URL 前统一走 `resolve_editor_reference_object_key_for_owner(state, owner_user_id, source)`,先在当前账号的项目资源、素材库资产或 `asset_object` 中匹配 owner / bucket / key。只有确实需要图片字节的入口(生成 / 重绘 / 图标 / UI 提取等交给 provider 的路径)再走 `parse_editor_reference_image`(内部仍先 resolve,再下载 OSS 字节);手动去背景等只签发短期 URL 的入口不要 `parse` 整图。图标素材等额外参考图必须真实传到 provider,不只写 metadata;图片快速编辑当前不开放额外参考图,若后续重开入口也必须沿用同一归属校验。
- 处理:所有私有对象引用在读取字节或签发 URL 前统一走 `resolve_editor_reference_object_key_for_owner(state, owner_user_id, source)`,先在当前账号的项目资源、素材库资产或 `asset_object` 中匹配 owner / bucket / key。只有确实需要图片字节的入口(生成 / 重绘 / 图标 / UI 提取等交给 provider 的路径)再走 `parse_editor_reference_image`(内部仍先 resolve,再下载 OSS 字节);手动去背景等只签发短期 URL 的入口不要 `parse` 整图。手动去背景还要恢复源模型时,object key 解析、所有权校验和源模型回溯必须复用同一轮账号项目 / 素材快照,项目与素材快照各最多读取一次;不得先走通用 resolver 全量读取,再为模型回溯重复拉取完整画布和素材库。图标素材等额外参考图必须真实传到 provider,不只写 metadata;图片快速编辑当前不开放额外参考图,若后续重开入口也必须沿用同一归属校验。
- 验证:`cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_reference`,并用前端 workflow 测试覆盖 `referenceImageSrcs` 进入图标生成请求;若快速编辑重开额外参考图,再补对应请求覆盖。
- 关联:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/spacetime-client/src/assets.rs`、`src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts`。
@@ -3982,3 +3982,19 @@
- 现象:为了让 Runtime 调用中立 trait,在 core 或 AGC 内再拼一次 URL/header/request body,或自己消费 SSE;它会与 `platform-llm` 的重试、脱敏、工具分片和错误分类迅速漂移。
- 处理:adapter 只做 core DTO 与现有 `Llm*` DTO 转换,网络调用唯一落到 `LlmClient::run/stream_run`。流式 sink 保留累计文本、当前增量和 finish reason;tool calls 继续从最终 response 读取。
- 验证:三种 descriptor/capability、request/response round-trip、stream callback 和稳定 error kind 单测后,仍必须运行 `platform-llm` 全量 parser 测试;只有 adapter fake 通过不能证明 wire 协议没有回归。
## 内部处理模型的可见性过滤是标题精确匹配,不是语义识别
- 现象:读文档以为「内部处理模型不会展示给普通用户」是全覆盖保证,实际历史素材的图片信息弹窗和画布 ZIP 导出里仍能看到抠图模型,例如标题“抠图模型”、取值 `动漫风格 anime-seg`。
- 原因:`isEditorUserVisibleGenerationInputField` 的实现是 `field.title.trim() !== '处理模型'`,只按这一个标题字符串精确排除,既不识别语义也不探测取值。历史数据里存在标题不同但语义相同的字段,直接穿过过滤器;服务端 User/Public mapper 只清理 `generationInputs` 顶层的 `screenColorHex` / `mattingProvider` / `mattingModel`,不遍历 `fields` 数组,所以两侧都不会拦。
- 处理:本条目前不修——历史素材不迁移、不回溯清理是明确的产品决策,不得据此判定为缺陷或提交「修复」。约束只对新写入生效:新产生的 `generationInputs.fields` 不得再写入任何内部处理模型字段,无论标题叫什么。若将来要扩大过滤范围,先对生产 `generation_inputs_json` 做一次标题去重查询枚举真实存在的历史标题,不要仅凭测试夹具推断清单。
- 验证:`ImageCanvasMetadataModalView` 与 `ImageCanvasExportModel` 共用同一过滤口径,改动其一必须同时覆盖另一侧;新增过滤标题时需同时确认图片信息弹窗与画布 ZIP 两条路径。
- 关联:`src/components/image-editor/ImageCanvasGenerationModel.ts`(`isEditorUserVisibleGenerationInputField`)、`src/components/image-editor/ImageCanvasExportModel.ts`、`src/components/image-editor/ImageCanvasMetadataModalView.tsx`、`src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
## 外部 OpenAPI v1 的「无调用方」豁免不是受控状态
- 现象:认为外部 v1 契约可以随内部脱敏需要直接改,因为「反正没人接」;`docs/openapi/genarrative-external-v1.openapi.json` 被当成内部文档同步,不走版本流程。
- 原因:API Key 由用户在个人中心 `我的 → 开发者 API Key` 自助发放,`/api/external/v1/openapi.json` 又是该批路由里唯一不要求鉴权的端点,任何登录用户都能拉规格并生成客户端。因此「无外部调用方」随时可能在无人决策的情况下变为假,不能当作长期前提。
- 处理:改外部 v1 响应前先确认 `external_api_key` 是否已有非内部账号的活跃密钥。仍无调用方时可按现行豁免直接改,但必须同步更新接入方案的「版本与兼容策略」;已有调用方时按该节规则择一处理(兼容值 / 弃用期 / 升 v2),只改 JSON 不构成合规变更。
- 验证:`external_editor_api.rs` 的 openapi 断言只校验 schema 形状,不校验兼容性,通过不等于契约安全;判定 breaking 与否以「删字段、移出 required、收窄类型、改语义、新增必填」为准。
- 关联:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`、`docs/openapi/genarrative-external-v1.openapi.json`、`server-rs/crates/api-server/src/external_editor_api.rs`、`server-rs/crates/api-server/src/modules/external_api.rs`。
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -61,6 +61,44 @@ DELETE /api/profile/api-keys/{keyId}
前端入口位于登录后个人中心的 `我的 → 开发者 API Key`,用于查看当前 Key、创建新 Key、复制一次性明文和撤销已创建 Key。外部 OpenAPI 只描述 `/api/external/v1` 下可由 API Key 调用的接口,不混入登录态 API Key 管理接口。
## 版本与兼容策略
### 当前状态:v1 尚无外部存量调用方
截至 2026-07-31,`external_api_key` 表内没有属于外部第三方的存量调用方,v1 处于「已发布但无存量集成」阶段。本节记录的豁免只在该前提成立时有效。
### 已接受的未版本化 breaking change
2026-07-31「收紧编辑器内部处理元数据边界」从下列响应中移除了原本 `required` 的 `provider`,`info.version` 保持 `1.0.0`,路径前缀保持 `/api/external/v1`:
- `EditorImageGenerationResponse`、`EditorIconSpritesheetGenerationResponse`、`EditorVideoGenerationResponse`、`EditorAudioGenerationResponse`:`provider` 原为 `required` 且非空 `string`,属性整体移除,JSON key 不再出现。
- `EditorProjectResource`、`EditorAsset`:`provider` 原为可选 nullable,属性移除后同样不再出现在响应中。
受影响端点为 `POST /api/external/v1/editor/images/generations`、`.../images/edits`、`.../icon-spritesheets/generations`、`.../ui-designs/assets/extractions`、`.../videos/generations`、`.../audios/sound-effects/generations`、`.../audios/background-music/generations`,以及全部引用上述两个资源 schema 的读取端点。
这是 breaking change,不是文档同步:严格反序列化的调用方(OpenAPI Generator 生成的 Java / Kotlin / C#、pydantic、serde 非 `Option` 字段)在 `required` 字段缺失时直接失败,且失败发生在服务端上线瞬间,不需要调用方做任何动作。脱敏目标本身成立,接受不升版本、不设弃用期的唯一依据是当前无存量调用方。
### 豁免的失效条件
API Key 由用户在个人中心自助发放,因此「无外部调用方」不是受控状态,可能在无人决策的情况下变为假。本节豁免在下列任一条件出现后立即失效:
- `external_api_key` 出现属于非内部账号的活跃密钥;
- 对外公布 v1 契约、接入文档或示例代码;
- 与外部团队开始基于 v1 的联调。
正式对外发放第一个外部密钥之前,必须先确认下节规则已生效且 v1 契约已冻结。
### 今后的变更规则
下列改动视为 breaking,不得在同一 `info.version` 与同一路径前缀下直接发布:
- 删除响应字段,或把响应字段移出 `required`;
- 收窄字段类型、取值枚举或长度约束;
- 在不改字段名的前提下改变字段语义;
- 新增请求必填字段,或收紧既有请求字段的校验。
存量调用方出现后,上述改动按以下顺序择一处理:保留字段并返回兼容值(可为 `null` 或占位值);标注 `deprecated` 并公告弃用期后再移除;或开设 `/api/external/v2` 并冻结 v1。仅更新 `docs/openapi/genarrative-external-v1.openapi.json` 不构成合规的变更流程。
## 鉴权
外部调用使用 Bearer API Key:
@@ -116,7 +154,7 @@ SpacetimeDB procedure:
1. 通过 OSS / asset object adapter 持久化媒体文件。
2. 写入 `editor_asset`,让生成素材进入账号级素材库。
3. 如果请求带 `projectId`,写入 `editor_project_resource`。
4. 返回图片读取地址、素材 ID、资源 ID、尺寸、prompt、model、provider 和 taskId。
4. 返回图片读取地址、素材 ID、资源 ID、尺寸、prompt、model 和 taskId;普通 External API 响应、项目资源与素材 read model 不返回生成 provider 或内部抠图审计字段。同源画布前端自动提交默认 `segModel` 属于站内 BFF 请求契约,不因此向 External OpenAPI 开放该字段。
如果请求未带 `projectId`,只生成并写入素材库;调用方可随后创建项目或自行保存画板布局。