From 4024ea53ed5b745f1e61449848b8ee9cafe40351 Mon Sep 17 00:00:00 2001 From: Linghong Date: Sat, 8 Aug 2026 09:19:32 +0000 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20External=20v1=20=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E7=BB=93=E6=9E=9C=E8=81=94=E5=90=88=E7=9A=84=20discri?= =?UTF-8?q?minator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BGM 回 audioKind=background-music 无映射,图片、视频与历史结果没有 audioKind,fallback 分支又不可能把 audioKind 声明为必填,任何映射都覆盖 不全合法结果。oneOf 加 not 本已精确互斥,删掉 discriminator 不改变校验 语义,只恢复依赖它的客户端生成 契约测试反向锁定 discriminator 缺席,并锁定 fallback 只排除 SFX 一种 audioKind Co-Authored-By: Claude Opus 5 --- .../genarrative-external-v1.openapi.json | 10 ++------ .../api-server/src/external_editor_api.rs | 25 +++++++++++++------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/openapi/genarrative-external-v1.openapi.json b/docs/openapi/genarrative-external-v1.openapi.json index e4f67a56b..74a73eba0 100644 --- a/docs/openapi/genarrative-external-v1.openapi.json +++ b/docs/openapi/genarrative-external-v1.openapi.json @@ -4945,7 +4945,7 @@ } }, "additionalProperties": true, - "description": "其它生成类型或历史结果的兼容 compact result。该 fallback 明确排除 audioKind=sound-effect,避免吞掉 SFX 专用分支。" + "description": "其它生成类型或历史结果的兼容 compact result。背景音乐(audioKind=background-music)与不带 audioKind 的图片、视频、图标序列帧、角色动作和 UI 拆解结果都落在这里。该 fallback 明确排除 audioKind=sound-effect,避免吞掉 SFX 专用分支。" }, "ExternalEditorGenerationCompletedResult": { "oneOf": [ @@ -4956,13 +4956,7 @@ "$ref": "#/components/schemas/ExternalEditorGenerationGenericCompactResult" } ], - "discriminator": { - "propertyName": "audioKind", - "mapping": { - "sound-effect": "#/components/schemas/ExternalEditorSoundEffectCompactResult" - } - }, - "description": "External v1 轮询 completed 状态的命名 compact result 联合。" + "description": "External v1 轮询 completed 状态的命名 compact result 联合。两个分支已由 audioKind 的 const 与 not 精确互斥,不使用 discriminator:背景音乐返回 audioKind=background-music,图片、视频、图标序列帧、角色动作、UI 拆解与历史结果根本没有 audioKind,它们都无法映射到具名分支,且 fallback 分支不可能把 audioKind 声明为必填,因此任何 discriminator 映射都不可能覆盖全部合法结果。" }, "ExternalEditorGenerationSubmissionResponse": { "type": "object", diff --git a/server-rs/crates/api-server/src/external_editor_api.rs b/server-rs/crates/api-server/src/external_editor_api.rs index 83c43bf39..2deed567d 100644 --- a/server-rs/crates/api-server/src/external_editor_api.rs +++ b/server-rs/crates/api-server/src/external_editor_api.rs @@ -2179,13 +2179,11 @@ mod tests { completed_result["oneOf"][1]["$ref"], "#/components/schemas/ExternalEditorGenerationGenericCompactResult" ); - assert_eq!( - completed_result["discriminator"]["propertyName"], - "audioKind" - ); - assert_eq!( - completed_result["discriminator"]["mapping"]["sound-effect"], - "#/components/schemas/ExternalEditorSoundEffectCompactResult" + assert!( + completed_result.get("discriminator").is_none(), + "completed result 联合不能带 discriminator:BGM 回 audioKind=background-music,图片、\ + 视频与历史结果没有 audioKind,而 fallback 分支不可能把 audioKind 声明为必填,\ + 任何映射都覆盖不全合法结果" ); let sound_effect_result = &parsed["components"]["schemas"]["ExternalEditorSoundEffectCompactResult"]; @@ -2230,6 +2228,19 @@ mod tests { generic_result["not"]["properties"]["audioKind"]["const"], "sound-effect" ); + assert_eq!( + generic_result["not"]["properties"] + .as_object() + .map(serde_json::Map::len), + Some(1), + "fallback 只能排除 SFX 一种 audioKind;再排除别的值会把 BGM 等合法结果挤出联合" + ); + assert!( + generic_result["not"]["properties"]["audioKind"] + .get("enum") + .is_none(), + "排除条件必须是 const sound-effect,换成 enum 会连带排掉 BGM" + ); assert!( parsed["paths"] .get("/api/external/v1/editor/audios/background-music/generations")