收紧 AGC 资源 kind 类型边界并统一族判据

- 将 manifest 与本地导入回执的资源 kind 改为 ts-rs 生成绑定

- 集中音频与视觉资源族判据并复用 Rust 枚举方法

- 放宽 Unknown 未解析语义并清理上传类型墓碑注释

- 标记共享生成绑定并同步项目决策与实施计划
This commit is contained in:
2026-09-18 15:07:36 +08:00
parent 03d7bca9a5
commit e5fd454bb3
16 changed files with 175 additions and 47 deletions
@@ -25,6 +25,8 @@ import {
gameCreationAppAssetPersistedCategory,
gameCreationAppAssetTags,
type GameCreationAppManifest,
isGameCreationAppAssetAudioKind,
isGameCreationAppAssetVisualKind,
isGameCreationAppUiDesignDocAsset,
normalizeGameCreationAppAssetCategory,
normalizeGameCreationAppAssetTags,
@@ -798,6 +800,24 @@ describe('AI 游戏创作 App 共享契约', () => {
}
});
it('shares exhaustive audio and visual kind families', () => {
expect(
GAME_CREATION_APP_ASSET_KINDS.filter(isGameCreationAppAssetAudioKind),
).toEqual(['audio', 'sound-effect', 'background-music']);
expect(
GAME_CREATION_APP_ASSET_KINDS.filter(isGameCreationAppAssetVisualKind),
).toEqual([
'image',
'scene',
'character',
'character-animation',
'icon',
'icon-spritesheet',
'icon-spec',
'ui-design',
]);
});
it('识别 UI 编辑器文档资产只认 kind + mediaType 的唯一定义', () => {
expect(
isGameCreationAppUiDesignDocAsset({
@@ -468,7 +468,7 @@ export interface GameCreationAppAssetSource {
export interface GameCreationAppAssetManifestEntry {
id: string;
kind: string;
kind: GameCreationAppAssetKind;
mediaType: string;
localPath: string;
source: GameCreationAppAssetSource;
@@ -556,6 +556,54 @@ export const GAME_CREATION_APP_ASSET_KINDS: readonly GameCreationAppAssetKind[]
GAME_CREATION_APP_ASSET_KIND_MEMBERS,
) as GameCreationAppAssetKind[];
const GAME_CREATION_APP_AUDIO_ASSET_KIND_MEMBERS: Record<
Extract<
GameCreationAppAssetKind,
'audio' | 'sound-effect' | 'background-music'
>,
true
> = {
audio: true,
'sound-effect': true,
'background-music': true,
};
const GAME_CREATION_APP_VISUAL_ASSET_KIND_MEMBERS: Record<
Extract<
GameCreationAppAssetKind,
| 'image'
| 'scene'
| 'character'
| 'character-animation'
| 'icon'
| 'icon-spritesheet'
| 'icon-spec'
| 'ui-design'
>,
true
> = {
image: true,
scene: true,
character: true,
'character-animation': true,
icon: true,
'icon-spritesheet': true,
'icon-spec': true,
'ui-design': true,
};
export function isGameCreationAppAssetAudioKind(
kind: GameCreationAppAssetKind,
): boolean {
return kind in GAME_CREATION_APP_AUDIO_ASSET_KIND_MEMBERS;
}
export function isGameCreationAppAssetVisualKind(
kind: GameCreationAppAssetKind,
): boolean {
return kind in GAME_CREATION_APP_VISUAL_ASSET_KIND_MEMBERS;
}
const GAME_CREATION_APP_ASSET_KIND_SET = new Set<string>(
GAME_CREATION_APP_ASSET_KINDS,
);
@@ -4,7 +4,7 @@
* GameCreationApp manifest 资源 kind 的**唯一**类型,也是 TS 侧 kind union 的唯一真源
* (经 ts-rs 生成,前端不再手写第二份列表)。
*
* JSON 使用 kebab-case`Unknown` 表示解析边界遇到尚未登记的输入
* 正常资源写入路径不应主动选择它
* JSON 使用 kebab-case`Unknown` 表示当前边界无法解析输入
* 写入方可以保留这个未解析结果,但必须由调用者决定是否拒绝写入或交给后续归类
*/
export type GameCreationAppAssetKind = "image" | "scene" | "character" | "character-animation" | "icon" | "icon-spritesheet" | "icon-spec" | "ui-design" | "ui-design-doc" | "publication-material" | "spec" | "video" | "audio" | "sound-effect" | "background-music" | "font" | "document" | "code" | "unknown";