新增旧玩法表阶段一清空迁移能力
Project CI / Repository checks (pull_request) Failing after 9s
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Frontend tests (pull_request) Successful in 3m27s
Project CI / Native shell tests (pull_request) Failing after 17m36s

增加受 migration operator 保护的固定 63 张旧表清空 procedure
生成 spacetime-client procedure、输入和结果绑定
更新后端数据契约与两阶段退役决策记录
清理未挂载的旧入口、分享路由、快照持久化与旧状态死链
清理未挂载的后台旧入口、api-server 旧玩法模块与旧 prompt
清理未挂载的 SpacetimeDB 旧模块根文件与前端类型孤儿
This commit is contained in:
2026-09-02 16:28:14 +08:00
parent 5de9554426
commit 455f056c61
1454 changed files with 358 additions and 582058 deletions
@@ -1,229 +0,0 @@
import { describe, expect, test } from 'vitest';
import {
BARK_BATTLE_ASSET_SLOTS,
BARK_BATTLE_DIFFICULTY_PRESETS,
type BarkBattleDraftConfig,
type BarkBattleDraftConfigUpdateRequest,
type BarkBattleFinishResponse,
type BarkBattleGeneratedImageAsset,
type BarkBattleImageAssetGenerateRequest,
type BarkBattlePersonalBestSummary,
type BarkBattleWorkStats,
} from './barkBattle';
describe('Bark Battle shared contracts', () => {
test('default draft config fixture uses normal difficulty and v1 description fields', () => {
const draft: BarkBattleDraftConfig = {
draftId: 'draft-bark-1',
workId: 'work-bark-1',
configVersion: 2,
rulesetVersion: 'bark-battle-ruleset-v1',
title: '汪汪声浪挑战',
description: '轻配置草稿',
themeDescription: '傍晚城市公园里的声浪擂台',
playerImageDescription: '戴红围巾的柯基主角',
opponentImageDescription: '蓝色运动头带的哈士奇对手',
onomatopoeia: ['轰汪!', '嗷呜!', '咚咚!'],
playerCharacterImageSrc: '/generated-bark-battle/player/image.png',
opponentCharacterImageSrc: 'https://example.test/opponent.png',
uiBackgroundImageSrc: '/generated-bark-battle/ui/background.png',
difficultyPreset: 'normal',
updatedAt: '2026-05-13T03:00:00.000Z',
};
expect(BARK_BATTLE_DIFFICULTY_PRESETS).toEqual(['easy', 'normal', 'hard']);
expect(draft.difficultyPreset).toBe('normal');
expect(Object.keys(draft)).toEqual([
'draftId',
'workId',
'configVersion',
'rulesetVersion',
'title',
'description',
'themeDescription',
'playerImageDescription',
'opponentImageDescription',
'onomatopoeia',
'playerCharacterImageSrc',
'opponentCharacterImageSrc',
'uiBackgroundImageSrc',
'difficultyPreset',
'updatedAt',
]);
expect(draft.playerCharacterImageSrc).toContain('/generated-bark-battle/');
expect('barkSoundSrc' in draft).toBe(false);
expect('leaderboardEnabled' in draft).toBe(false);
});
test('draft config update contract persists generated image slots only', () => {
const update: BarkBattleDraftConfigUpdateRequest = {
draftId: 'draft-bark-1',
workId: 'BB-12345678',
configVersion: 2,
rulesetVersion: 'bark-battle-ruleset-v1',
title: '汪汪声浪挑战',
description: '轻配置草稿',
themeDescription: '傍晚城市公园里的声浪擂台',
playerImageDescription: '戴红围巾的柯基主角',
opponentImageDescription: '蓝色运动头带的哈士奇对手',
onomatopoeia: ['轰!', '燃起来!', '破阵!'],
playerCharacterImageSrc: '/generated-bark-battle/player/image.png',
opponentCharacterImageSrc: '/generated-bark-battle/opponent/image.png',
uiBackgroundImageSrc: '/generated-bark-battle/ui/background.png',
difficultyPreset: 'normal',
};
expect(Object.keys(update)).toEqual([
'draftId',
'workId',
'configVersion',
'rulesetVersion',
'title',
'description',
'themeDescription',
'playerImageDescription',
'opponentImageDescription',
'onomatopoeia',
'playerCharacterImageSrc',
'opponentCharacterImageSrc',
'uiBackgroundImageSrc',
'difficultyPreset',
]);
expect('barkSoundSrc' in update).toBe(false);
expect('leaderboardEnabled' in update).toBe(false);
});
test('image generation contract uses dedicated Bark Battle slots and backend prompt result', () => {
expect(BARK_BATTLE_ASSET_SLOTS).toEqual([
'player-character',
'opponent-character',
'ui-background',
]);
const request: BarkBattleImageAssetGenerateRequest = {
slot: 'opponent-character',
draftId: 'bark-battle-draft-1',
config: {
title: '汪汪冠军杯',
description: '',
themeDescription: '霓虹公园擂台',
playerImageDescription: '红围巾柴犬',
opponentImageDescription: '蓝头带哈士奇',
onomatopoeia: ['轰汪!', '炸场!', '冲啊!'],
difficultyPreset: 'normal',
},
};
const response: BarkBattleGeneratedImageAsset = {
imageSrc: '/generated-bark-battle-assets/draft/opponent/image.webp',
assetId: 'asset-1',
sourceType: 'generated',
model: 'gpt-image-2',
size: '1024*1024',
taskId: 'task-1',
prompt: '后端拼装后的对手形象 prompt',
};
expect(JSON.parse(JSON.stringify(request))).toMatchObject({
slot: 'opponent-character',
config: {
opponentImageDescription: '蓝头带哈士奇',
onomatopoeia: ['轰汪!', '炸场!', '冲啊!'],
},
});
expect(JSON.parse(JSON.stringify(response))).toMatchObject({
imageSrc: '/generated-bark-battle-assets/draft/opponent/image.webp',
prompt: '后端拼装后的对手形象 prompt',
});
});
test('finish accepted player_win fixture exposes backend adjudication result', () => {
const response: BarkBattleFinishResponse = {
status: 'accepted',
runId: 'run-bark-1',
workId: 'work-bark-1',
configVersion: 3,
rulesetVersion: 'bark-battle-ruleset-v1',
difficultyPreset: 'hard',
serverResult: 'player_win',
scoreSummary: {
finalEnergy: 87,
triggerCount: 42,
maxVolume: 0.96,
averageVolume: 0.61,
comboMax: 9,
durationMs: 30000,
},
leaderboardScore: 870429630,
antiCheatFlags: [],
updatedAt: '2026-05-13T03:00:30.000Z',
};
expect(response.status).toBe('accepted');
expect(response.serverResult).toBe('player_win');
expect(response.scoreSummary.finalEnergy).toBe(87);
expect(response.antiCheatFlags).toEqual([]);
});
test('work stats fixture tracks starts, finishes, result counts, flags and energy summary', () => {
const stats: BarkBattleWorkStats = {
workId: 'work-bark-1',
configVersion: 3,
rulesetVersion: 'bark-battle-ruleset-v1',
difficultyPreset: 'normal',
playStartCount: 18,
finishCount: 15,
winCount: 8,
drawCount: 2,
lossCount: 5,
flaggedCount: 1,
leaderboardEntryCount: 7,
bestLeaderboardScore: 930389410,
bestFinalEnergy: 93,
averageFinalEnergy: 41.25,
updatedAt: '2026-05-13T04:00:00.000Z',
};
expect(stats.playStartCount).toBe(18);
expect(stats.finishCount).toBe(15);
expect(stats.winCount + stats.drawCount + stats.lossCount).toBe(15);
expect(stats.flaggedCount).toBe(1);
expect(stats.bestFinalEnergy).toBeGreaterThan(stats.averageFinalEnergy);
});
test('optional score fields may be omitted instead of serialized as null', () => {
const finishWithoutLeaderboard: BarkBattleFinishResponse = {
status: 'accepted',
runId: 'run-bark-no-rank',
workId: 'work-bark-1',
configVersion: 3,
rulesetVersion: 'bark-battle-ruleset-v1',
difficultyPreset: 'normal',
serverResult: 'draw',
scoreSummary: {
finalEnergy: 50,
triggerCount: 12,
maxVolume: 0.7,
averageVolume: 0.5,
comboMax: 3,
durationMs: 30000,
},
antiCheatFlags: [],
updatedAt: '2026-05-13T03:00:30.000Z',
};
const personalBestWithoutWin: BarkBattlePersonalBestSummary = {
workId: 'work-bark-1',
rulesetVersion: 'bark-battle-ruleset-v1',
difficultyPreset: 'normal',
winCount: 0,
drawCount: 1,
lossCount: 2,
finishCount: 3,
updatedAt: '2026-05-13T04:00:00.000Z',
};
expect('leaderboardScore' in finishWithoutLeaderboard).toBe(false);
expect('bestLeaderboardScore' in personalBestWithoutWin).toBe(false);
expect('bestFinalEnergy' in personalBestWithoutWin).toBe(false);
});
});
-312
View File
@@ -1,312 +0,0 @@
export const BARK_BATTLE_DIFFICULTY_PRESETS = [
'easy',
'normal',
'hard',
] as const;
export type BarkBattleDifficultyPreset =
(typeof BARK_BATTLE_DIFFICULTY_PRESETS)[number];
export type BarkBattleServerResult = 'player_win' | 'opponent_win' | 'draw';
export type BarkBattleFinishStatus =
| 'accepted'
| 'accepted_with_flags'
| 'rejected';
export type BarkBattlePlayTypeId = 'bark-battle';
export const BARK_BATTLE_ASSET_SLOTS = [
'player-character',
'opponent-character',
'ui-background',
] as const;
export type BarkBattleAssetSlot = (typeof BARK_BATTLE_ASSET_SLOTS)[number];
export interface BarkBattleReplacementConfig {
playerCharacterImageSrc?: string;
opponentCharacterImageSrc?: string;
uiBackgroundImageSrc?: string;
}
export type BarkBattleOnomatopoeia = string[];
export interface BarkBattleConfigEditorPayload
extends BarkBattleReplacementConfig {
title: string;
description?: string;
themeDescription: string;
playerImageDescription: string;
opponentImageDescription: string;
onomatopoeia?: BarkBattleOnomatopoeia;
difficultyPreset: BarkBattleDifficultyPreset;
}
export interface BarkBattleDraftCreateRequest
extends BarkBattleConfigEditorPayload {}
export interface BarkBattleDraftConfigUpdateRequest
extends BarkBattleConfigEditorPayload {
draftId: string;
workId?: string | null;
configVersion?: number;
rulesetVersion?: string;
}
export interface BarkBattleWorkPublishRequest {
draftId: string;
workId: string;
publishedSnapshot?: BarkBattleConfigEditorPayload;
}
export interface BarkBattleImageAssetGenerateRequest {
slot: BarkBattleAssetSlot;
draftId?: string | null;
billingPurpose?: 'initial_draft_generation' | null;
config: BarkBattleConfigEditorPayload;
}
export interface BarkBattleGeneratedImageAsset {
imageSrc: string;
assetId: string;
sourceType?: 'generated' | string;
model: string;
size: string;
taskId: string;
prompt: string;
actualPrompt?: string;
}
export interface BarkBattleDraftConfig extends BarkBattleConfigEditorPayload {
draftId: string;
workId?: string;
configVersion?: number;
rulesetVersion?: string;
updatedAt: string;
}
export interface BarkBattlePublishedConfig {
workId: string;
draftId?: string | null;
configVersion: number;
rulesetVersion: string;
playTypeId: BarkBattlePlayTypeId;
title: string;
description?: string;
themeDescription: string;
playerImageDescription: string;
opponentImageDescription: string;
onomatopoeia?: BarkBattleOnomatopoeia;
playerCharacterImageSrc?: string;
opponentCharacterImageSrc?: string;
uiBackgroundImageSrc?: string;
difficultyPreset: BarkBattleDifficultyPreset;
updatedAt: string;
publishedAt: string;
}
export type BarkBattleWorkStatus = 'draft' | 'published';
export type BarkBattleGenerationStatus =
| 'pending_assets'
| 'ready'
| 'partial_failed'
| string;
export interface BarkBattleWorkSummary {
workId: string;
draftId?: string | null;
ownerUserId: string;
authorDisplayName: string;
title: string;
summary: string;
themeDescription: string;
playerImageDescription: string;
opponentImageDescription: string;
onomatopoeia?: BarkBattleOnomatopoeia;
playerCharacterImageSrc?: string | null;
opponentCharacterImageSrc?: string | null;
uiBackgroundImageSrc?: string | null;
difficultyPreset: BarkBattleDifficultyPreset;
status: BarkBattleWorkStatus;
generationStatus?: BarkBattleGenerationStatus | null;
publishReady: boolean;
playCount: number;
finishCount?: number;
winCount?: number;
drawCount?: number;
lossCount?: number;
recentPlayCount7d?: number;
updatedAt: string;
publishedAt?: string | null;
}
export interface BarkBattleWorksResponse {
items: BarkBattleWorkSummary[];
}
export interface BarkBattleWorkDetailResponse {
item: BarkBattleWorkSummary;
}
export interface BarkBattleRuntimeConfig {
workId: string;
configVersion: number;
rulesetVersion: string;
playTypeId: BarkBattlePlayTypeId;
durationMs: number;
energyMin: number;
energyMax: number;
drawThreshold: number;
minBarkGapMs: number;
difficultyPreset: BarkBattleDifficultyPreset;
themeDescription: string;
playerImageDescription: string;
opponentImageDescription: string;
onomatopoeia?: BarkBattleOnomatopoeia;
playerCharacterImageSrc?: string;
opponentCharacterImageSrc?: string;
uiBackgroundImageSrc?: string;
updatedAt: string;
}
export interface BarkBattleRunStartRequest {
workId: string;
configVersion?: number;
sourceRoute?: string;
clientRuntimeVersion?: string;
}
export interface BarkBattleRunStartResponse {
runId: string;
runToken: string;
workId: string;
configVersion: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
runtimeConfig: BarkBattleRuntimeConfig;
serverStartedAt: string;
expiresAt: string;
}
export interface BarkBattleDerivedMetrics {
triggerCount: number;
maxVolume: number;
averageVolume: number;
finalEnergy: number;
comboMax: number;
}
export interface BarkBattleRunFinishRequest {
runId: string;
runToken: string;
workId: string;
configVersion: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
clientStartedAt: string;
clientFinishedAt: string;
durationMs: number;
derivedMetrics: BarkBattleDerivedMetrics;
clientResult?: BarkBattleServerResult;
sampleDigest?: string;
clientRuntimeVersion?: string;
}
export interface BarkBattleScoreSummary extends BarkBattleDerivedMetrics {
durationMs: number;
}
export interface BarkBattleFinishResponse {
status: BarkBattleFinishStatus;
runId: string;
workId: string;
configVersion: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
serverResult: BarkBattleServerResult;
scoreSummary: BarkBattleScoreSummary;
leaderboardScore?: number;
antiCheatFlags: string[];
updatedAt: string;
}
export interface BarkBattleLeaderboardEntry {
rank: number;
runId: string;
workId: string;
configVersion: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
displayName: string;
serverResult: BarkBattleServerResult;
scoreSummary: BarkBattleScoreSummary;
leaderboardScore: number;
updatedAt: string;
}
export interface BarkBattleLeaderboardResponse {
workId: string;
configVersion?: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
entries: BarkBattleLeaderboardEntry[];
viewerBest?: BarkBattleLeaderboardEntry | null;
updatedAt: string;
}
export interface BarkBattlePersonalHistoryItem {
runId: string;
workId: string;
configVersion: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
serverResult: BarkBattleServerResult;
scoreSummary: BarkBattleScoreSummary;
leaderboardScore?: number;
antiCheatFlags: string[];
updatedAt: string;
}
export interface BarkBattlePersonalBestSummary {
workId: string;
configVersion?: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
bestLeaderboardScore?: number;
bestFinalEnergy?: number;
bestTriggerCount?: number;
bestMaxVolume?: number;
winCount: number;
drawCount: number;
lossCount: number;
finishCount: number;
updatedAt: string;
}
export interface BarkBattlePersonalHistoryResponse {
workId?: string;
difficultyPreset?: BarkBattleDifficultyPreset;
items: BarkBattlePersonalHistoryItem[];
bestSummary?: BarkBattlePersonalBestSummary | null;
updatedAt: string;
}
export interface BarkBattleWorkStats {
workId: string;
configVersion?: number;
rulesetVersion: string;
difficultyPreset: BarkBattleDifficultyPreset;
playStartCount: number;
finishCount: number;
winCount: number;
drawCount: number;
lossCount: number;
flaggedCount: number;
leaderboardEntryCount: number;
bestLeaderboardScore?: number;
bestFinalEnergy?: number;
averageFinalEnergy?: number;
updatedAt: string;
}
-199
View File
@@ -1,199 +0,0 @@
/**
* 大鱼吃小鱼玩法域前端共享契约。
* 字段与 server-rs/shared-contracts/src/big_fish.rs 保持 camelCase 对齐。
*/
export type CreateBigFishSessionRequest = {
seedText?: string;
};
export type SendBigFishMessageRequest = {
clientMessageId: string;
text: string;
quickFillRequested?: boolean;
};
export type BigFishActionId =
| 'big_fish_compile_draft'
| 'big_fish_generate_level_main_image'
| 'big_fish_generate_level_motion'
| 'big_fish_generate_stage_background'
| 'big_fish_publish_game';
export type ExecuteBigFishActionRequest = {
action: BigFishActionId;
level?: number;
motionKey?: 'idle_float' | 'move_swim' | string;
};
export type RecordBigFishPlayRequest = {
elapsedMs?: number;
};
export type SubmitBigFishInputRequest = {
x: number;
y: number;
};
export type BigFishAnchorStatus =
| 'confirmed'
| 'inferred'
| 'missing'
| 'locked'
| string;
export type BigFishAnchorItemResponse = {
key: string;
label: string;
value: string;
status: BigFishAnchorStatus;
};
export type BigFishAnchorPackResponse = {
gameplayPromise: BigFishAnchorItemResponse;
ecologyVisualTheme: BigFishAnchorItemResponse;
growthLadder: BigFishAnchorItemResponse;
riskTempo: BigFishAnchorItemResponse;
};
export type BigFishLevelBlueprintResponse = {
level: number;
name: string;
oneLineFantasy: string;
textDescription: string;
silhouetteDirection: string;
sizeRatio: number;
visualDescription: string;
visualPromptSeed: string;
idleMotionDescription: string;
moveMotionDescription: string;
motionPromptSeed: string;
mergeSourceLevel?: number | null;
preyWindow: number[];
threatWindow: number[];
isFinalLevel: boolean;
};
export type BigFishBackgroundBlueprintResponse = {
theme: string;
colorMood: string;
foregroundHints: string;
midgroundComposition: string;
backgroundDepth: string;
safePlayAreaHint: string;
spawnEdgeHint: string;
backgroundPromptSeed: string;
};
export type BigFishRuntimeParamsResponse = {
levelCount: number;
mergeCountPerUpgrade: number;
spawnTargetCount: number;
leaderMoveSpeed: number;
followerCatchUpSpeed: number;
offscreenCullSeconds: number;
preySpawnDeltaLevels: number[];
threatSpawnDeltaLevels: number[];
winLevel: number;
};
export type BigFishGameDraftResponse = {
title: string;
subtitle: string;
coreFun: string;
ecologyTheme: string;
levels: BigFishLevelBlueprintResponse[];
background: BigFishBackgroundBlueprintResponse;
runtimeParams: BigFishRuntimeParamsResponse;
};
export type BigFishAgentMessageResponse = {
id: string;
role: 'user' | 'assistant' | string;
kind: 'chat' | 'system' | 'warning' | string;
text: string;
createdAt: string;
};
export type BigFishAssetKind =
| 'level_main_image'
| 'level_motion'
| 'stage_background'
| string;
export type BigFishAssetStatus = 'empty' | 'ready' | 'generating' | string;
export type BigFishAssetSlotResponse = {
slotId: string;
assetKind: BigFishAssetKind;
level?: number | null;
motionKey?: string | null;
status: BigFishAssetStatus;
assetUrl?: string | null;
promptSnapshot: string;
updatedAt: string;
};
export type BigFishAssetCoverageResponse = {
levelMainImageReadyCount: number;
levelMotionReadyCount: number;
backgroundReady: boolean;
requiredLevelCount: number;
publishReady: boolean;
blockers: string[];
};
export type BigFishSessionSnapshotResponse = {
sessionId: string;
currentTurn: number;
progressPercent: number;
stage: string;
anchorPack: BigFishAnchorPackResponse;
draft?: BigFishGameDraftResponse | null;
assetSlots: BigFishAssetSlotResponse[];
assetCoverage: BigFishAssetCoverageResponse;
messages: BigFishAgentMessageResponse[];
lastAssistantReply?: string | null;
publishReady: boolean;
updatedAt: string;
};
export type BigFishSessionResponse = {
session: BigFishSessionSnapshotResponse;
};
export type BigFishActionResponse = {
session: BigFishSessionSnapshotResponse;
};
export type BigFishVector2Response = {
x: number;
y: number;
};
export type BigFishRuntimeEntityResponse = {
entityId: string;
level: number;
position: BigFishVector2Response;
radius: number;
offscreenSeconds: number;
};
export type BigFishRuntimeSnapshotResponse = {
runId: string;
sessionId: string;
status: 'running' | 'won' | 'failed' | string;
tick: number;
playerLevel: number;
winLevel: number;
leaderEntityId?: string | null;
ownedEntities: BigFishRuntimeEntityResponse[];
wildEntities: BigFishRuntimeEntityResponse[];
cameraCenter: BigFishVector2Response;
lastInput: BigFishVector2Response;
eventLog: string[];
updatedAt: string;
};
export type BigFishRunResponse = {
run: BigFishRuntimeSnapshotResponse;
};
@@ -1,28 +0,0 @@
export type BigFishWorkStatus = 'draft' | 'published';
export interface BigFishWorkSummary {
workId: string;
sourceSessionId: string;
ownerUserId: string;
authorDisplayName: string;
title: string;
subtitle: string;
summary: string;
coverImageSrc: string | null;
status: BigFishWorkStatus;
updatedAt: string;
publishedAt?: string | null;
publishReady: boolean;
levelCount: number;
levelMainImageReadyCount: number;
levelMotionReadyCount: number;
backgroundReady: boolean;
playCount?: number;
remixCount?: number;
likeCount?: number;
recentPlayCount7d?: number;
}
export interface BigFishWorksResponse {
items: BigFishWorkSummary[];
}
@@ -1,17 +0,0 @@
export interface ParseCreationAgentDocumentInputRequest {
fileName: string;
contentType?: string | null;
contentBase64: string;
}
export interface CreationAgentDocumentInputPayload {
fileName: string;
contentType?: string | null;
sizeBytes: number;
text: string;
sourceAssetId?: string | null;
}
export interface ParseCreationAgentDocumentInputResponse {
document: CreationAgentDocumentInputPayload;
}
@@ -1,56 +0,0 @@
export type CreationAudioGenerationKind = 'background_music' | 'sound_effect';
export interface CreationAudioAsset {
taskId: string;
provider: string;
assetObjectId?: string | null;
assetKind?: string | null;
audioSrc: string;
prompt?: string | null;
title?: string | null;
updatedAt?: string | null;
}
export interface CreateBackgroundMusicRequest {
prompt: string;
title: string;
tags?: string | null;
model?: string | null;
}
export interface CreateSoundEffectRequest {
prompt: string;
duration?: number | null;
seed?: number | null;
}
export interface AudioGenerationTaskResponse {
kind: CreationAudioGenerationKind;
taskId: string;
provider: string;
status: string;
}
export interface PublishGeneratedAudioAssetRequest {
entityKind: string;
entityId: string;
slot: string;
assetKind: string;
profileId?: string | null;
storagePrefix?:
| 'puzzle_assets'
| 'match3d_assets'
| 'wooden_fish_assets'
| 'custom_world_scenes'
| null;
}
export interface GeneratedAudioAssetResponse {
kind: CreationAudioGenerationKind;
taskId: string;
provider: string;
status: string;
assetObjectId?: string | null;
assetKind?: string | null;
audioSrc?: string | null;
}
@@ -1,244 +0,0 @@
import type { PuzzleResultDraft } from './puzzleAgentDraft';
import type { PuzzleAgentSessionSnapshot } from './puzzleAgentSession';
import type {
PuzzleCreativeTemplateProtocol,
PuzzleCreativeTemplateSelection,
PuzzleDraftFieldPatch,
PuzzleImageGenerationPlan,
PuzzleTemplateCostRange,
} from './puzzleCreativeTemplate';
export type CreativeAgentStage =
| 'idle'
| 'perceiving'
| 'thinking'
| 'remembering'
| 'selecting_puzzle_template'
| 'waiting_template_confirmation'
| 'planning_puzzle_levels'
| 'acting'
| 'reflecting'
| 'collaborating'
| 'target_ready'
| 'waiting_user'
| 'failed';
export type CreativeAgentEntryContext =
| 'creation_home'
| 'puzzle_workspace'
| 'gallery_remix'
| 'draft_restore';
export type CreativeAgentMessageRole = 'user' | 'assistant' | 'system';
export type CreativeAgentMessageKind =
| 'chat'
| 'stage'
| 'action_result'
| 'warning';
export type CreativeAgentInputPart =
| {
type: 'input_text';
text: string;
}
| {
type: 'input_image';
imageUrl: string;
assetId?: string | null;
thumbnailUrl?: string | null;
};
export interface CreativeImageInput {
assetId: string;
readUrl: string;
thumbnailUrl?: string | null;
width?: number | null;
height?: number | null;
}
export interface CreativeImageSummary {
assetId: string | null;
readUrl: string | null;
thumbnailUrl: string | null;
width: number | null;
height: number | null;
summary: string | null;
}
export type CreativeUnsupportedPlayType =
| 'rpg'
| 'match3d'
| 'big_fish'
| 'square_hole';
export interface CreativeUnsupportedCapability {
playType: CreativeUnsupportedPlayType;
title: string;
status: 'unsupported';
reason: string;
}
export interface CreativeInputSummary {
text: string | null;
entryContext: CreativeAgentEntryContext;
images: CreativeImageSummary[];
materialSummary: string | null;
unsupportedCapabilities: CreativeUnsupportedCapability[];
}
export interface CreativeAgentMessage {
id: string;
role: CreativeAgentMessageRole;
kind: CreativeAgentMessageKind;
text: string;
createdAt: string;
}
export interface CreativeTargetSessionBinding {
playType: 'puzzle';
targetSessionId: string;
targetStage: 'puzzle-agent-workspace' | 'puzzle-result' | 'puzzle-runtime';
resultProfileId: string | null;
}
export interface CreativeAgentSessionSnapshot {
sessionId: string;
stage: CreativeAgentStage;
inputSummary: CreativeInputSummary;
messages: CreativeAgentMessage[];
puzzleTemplateCatalog: PuzzleCreativeTemplateProtocol[];
puzzleTemplateSelection: PuzzleCreativeTemplateSelection | null;
puzzleImageGenerationPlan: PuzzleImageGenerationPlan | null;
targetBinding: CreativeTargetSessionBinding | null;
updatedAt: string;
}
export interface CreateCreativeAgentSessionRequest {
text?: string | null;
images?: CreativeImageInput[];
entryContext?: CreativeAgentEntryContext;
}
export interface CreativeAgentSessionResponse {
session: CreativeAgentSessionSnapshot;
}
export interface StreamCreativeAgentMessageRequest {
clientMessageId: string;
content: CreativeAgentInputPart[];
}
export interface ConfirmCreativePuzzleTemplateRequest {
selection: PuzzleCreativeTemplateSelection;
}
export interface CreativeDraftEditStreamRequest {
clientMessageId: string;
instruction: string;
targetPuzzleSessionId: string;
currentDraft: PuzzleResultDraft;
}
export interface CreativeDraftEditResult {
editInstructions: PuzzleDraftFieldPatch[];
session: CreativeAgentSessionSnapshot;
puzzleSession: PuzzleAgentSessionSnapshot;
}
export interface CreativeAgentStageEvent {
sessionId: string;
stage: CreativeAgentStage;
}
export interface CreativeAgentMessageDeltaEvent {
sessionId: string;
messageId: string;
role: CreativeAgentMessageRole;
kind: CreativeAgentMessageKind;
textDelta: string;
}
export interface CreativeAgentThoughtSummaryDeltaEvent {
sessionId: string;
thoughtId: string;
textDelta: string;
}
export interface CreativeAgentTemplateCatalogEvent {
sessionId: string;
templates: PuzzleCreativeTemplateProtocol[];
}
export interface CreativeAgentTemplateSelectionEvent {
sessionId: string;
selection: PuzzleCreativeTemplateSelection;
}
export interface CreativeAgentCostRangeEvent {
sessionId: string;
costRange: PuzzleTemplateCostRange;
}
export interface CreativeAgentLevelPlanEvent {
sessionId: string;
plan: PuzzleImageGenerationPlan;
}
export interface CreativeAgentToolEvent {
sessionId: string;
toolCallId: string;
toolName: string;
summary: string | null;
}
export interface CreativeAgentReflectionEvent {
sessionId: string;
pass: boolean;
summary: string;
warnings: string[];
}
export interface CreativeAgentTargetSessionEvent {
sessionId: string;
binding: CreativeTargetSessionBinding;
}
export interface CreativeAgentErrorEvent {
sessionId: string | null;
code: string;
message: string;
recoverable: boolean;
}
export interface CreativeAgentDoneEvent {
sessionId: string;
}
export type CreativeAgentSseEvent =
| { event: 'stage'; data: CreativeAgentStageEvent }
| { event: 'agent_message_delta'; data: CreativeAgentMessageDeltaEvent }
| {
event: 'thought_summary_delta';
data: CreativeAgentThoughtSummaryDeltaEvent;
}
| {
event: 'puzzle_template_catalog';
data: CreativeAgentTemplateCatalogEvent;
}
| {
event: 'puzzle_template_selection';
data: CreativeAgentTemplateSelectionEvent;
}
| { event: 'puzzle_cost_range'; data: CreativeAgentCostRangeEvent }
| { event: 'puzzle_level_plan'; data: CreativeAgentLevelPlanEvent }
| { event: 'tool_started'; data: CreativeAgentToolEvent }
| { event: 'tool_completed'; data: CreativeAgentToolEvent }
| { event: 'reflection'; data: CreativeAgentReflectionEvent }
| { event: 'target_session'; data: CreativeAgentTargetSessionEvent }
| {
event: 'session';
data: { session: CreativeAgentSessionSnapshot };
}
| { event: 'error'; data: CreativeAgentErrorEvent }
| { event: 'done'; data: CreativeAgentDoneEvent };
@@ -1,12 +0,0 @@
/**
* 兼容出口:
* 当前仓库仍有大量旧 customWorld 命名导入,这个文件继续作为过渡层保留。
* 工作包 H 完成后,真实类型定义已经迁移到 rpg* 契约文件中;这里仅聚合旧命名分文件。
*/
export type * from './customWorldAgentActions';
export type * from './customWorldAgentAnchors';
export type * from './customWorldAgentDraft';
export type * from './customWorldAgentSession';
export type * from './customWorldResultPreview';
export type * from './customWorldWorkSummary';
@@ -1,14 +0,0 @@
/**
* 旧 custom world 动作契约兼容出口。
* 后续若逐步迁移旧代码,建议直接改用 rpgAgentActions.ts。
*/
export type {
RpgAgentActionRequest as CustomWorldAgentActionRequest,
RpgAgentActionResponse as CustomWorldAgentActionResponse,
RpgAgentOperationRecord as CustomWorldAgentOperationRecord,
RpgAgentOperationStatus as CustomWorldAgentOperationStatus,
RpgAgentOperationType as CustomWorldAgentOperationType,
RpgAgentSuggestedAction as CustomWorldSuggestedAction,
RpgAgentSupportedAction as CustomWorldSupportedAction,
} from './rpgAgentActions';
@@ -1,9 +0,0 @@
/**
* 旧 custom world 八锚点兼容出口。
* 这里只保留旧命名到 RPG 创作域新契约的映射,便于旧导入渐进迁移。
*/
export type {
RpgCreationAnchorText as AnchorTextValue,
RpgCreationAnchorContent as EightAnchorContent,
} from './rpgAgentAnchors';
@@ -1,29 +0,0 @@
/**
* 旧 custom world 草稿契约兼容出口。
* 工作包 H 完成后,真实定义已经迁到 rpgAgentDraft.ts,这里只负责旧命名映射。
*/
export type {
RpgAgentAssetCoverageSummary as CustomWorldAssetCoverageSummary,
RpgAgentAssetPriorityTier as CustomWorldAssetPriorityTier,
RpgAgentDraftCardDetail as CustomWorldDraftCardDetail,
RpgAgentDraftCardDetailSection as CustomWorldDraftCardDetailSection,
RpgAgentDraftCardKind as CustomWorldDraftCardKind,
RpgAgentDraftCardStatus as CustomWorldDraftCardStatus,
RpgAgentDraftCardSummary as CustomWorldDraftCardSummary,
RpgAgentFoundationDraftCamp as CustomWorldFoundationDraftCamp,
RpgAgentFoundationDraftChapter as CustomWorldFoundationDraftChapter,
RpgAgentFoundationDraftCharacter as CustomWorldFoundationDraftCharacter,
RpgAgentFoundationDraftFaction as CustomWorldFoundationDraftFaction,
RpgAgentFoundationDraftLandmark as CustomWorldFoundationDraftLandmark,
RpgAgentFoundationDraftProfile as CustomWorldFoundationDraftProfile,
RpgAgentFoundationDraftResult as CustomWorldFoundationDraftResult,
RpgAgentFoundationDraftSceneAct as CustomWorldFoundationDraftSceneAct,
RpgAgentFoundationDraftSceneChapter as CustomWorldFoundationDraftSceneChapter,
RpgAgentFoundationDraftThread as CustomWorldFoundationDraftThread,
RpgAgentRoleAssetStatus as CustomWorldRoleAssetStatus,
RpgAgentRoleAssetSummary as CustomWorldRoleAssetSummary,
RpgAgentSceneActAdvanceRule as CustomWorldSceneActAdvanceRule,
RpgAgentSceneActStage as CustomWorldSceneActStage,
RpgAgentSceneAssetSummary as CustomWorldSceneAssetSummary,
} from './rpgAgentDraft';
@@ -1,20 +0,0 @@
/**
* 旧 custom world 会话契约兼容出口。
* 这一层只做命名映射,不再承担 session 真相源结构定义。
*/
export type {
CreateRpgAgentSessionRequest as CreateCustomWorldAgentSessionRequest,
CreateRpgAgentSessionResponse as CreateCustomWorldAgentSessionResponse,
RpgCreationIntentReadiness as CreatorIntentReadiness,
RpgAgentMessage as CustomWorldAgentMessage,
RpgAgentMessageKind as CustomWorldAgentMessageKind,
RpgAgentMessageRole as CustomWorldAgentMessageRole,
RpgAgentQualityFinding as CustomWorldAgentQualityFinding,
RpgAgentSessionSnapshot as CustomWorldAgentSessionSnapshot,
RpgAgentStage as CustomWorldAgentStage,
RpgAgentPendingClarification as CustomWorldPendingClarification,
GetRpgAgentCardDetailResponse as GetCustomWorldAgentCardDetailResponse,
SendRpgAgentMessageRequest as SendCustomWorldAgentMessageRequest,
SendRpgAgentMessageResponse as SendCustomWorldAgentMessageResponse,
} from './rpgAgentSession';
@@ -1,12 +0,0 @@
/**
* 旧 custom world 结果页预览兼容出口。
* 额外单独拆一个 preview 兼容文件,避免预览别名继续堆回 customWorldAgent.ts 聚合层。
*/
export type {
RpgCreationPreview as CustomWorldResultPreview,
RpgCreationPreviewBlocker as CustomWorldResultPreviewBlocker,
RpgCreationPreviewEnvelope as CustomWorldResultPreviewEnvelope,
RpgCreationPreviewFinding as CustomWorldResultPreviewFinding,
RpgCreationPreviewSource as CustomWorldResultPreviewSource,
} from './rpgCreationPreview';
@@ -1,11 +0,0 @@
/**
* 旧 custom world works 读模型兼容出口。
* 用于把旧作品列表命名平滑映射到新的 RPG 创作域 works 契约。
*/
export type {
RpgCreationWorkSource as CustomWorldWorkSource,
RpgCreationWorkStatus as CustomWorldWorkStatus,
RpgCreationWorkSummary as CustomWorldWorkSummary,
ListRpgCreationWorksResponse as ListCustomWorldWorksResponse,
} from './rpgCreationWorkSummary';
@@ -1,82 +0,0 @@
export const BABY_LOVE_DRAWING_TEMPLATE_ID = 'baby-love-drawing';
export const BABY_LOVE_DRAWING_TEMPLATE_NAME = '宝贝爱画';
export const BABY_LOVE_DRAWING_EDUTAINMENT_TAG = '寓教于乐';
export type BabyLoveDrawingTemplateId = typeof BABY_LOVE_DRAWING_TEMPLATE_ID;
export type BabyLoveDrawingTool = 'brush' | 'eraser';
export type BabyLoveDrawingSaveMode = 'original-only' | 'original-and-magic';
export type BabyLoveDrawingGenerationProvider =
| 'vector-engine-gpt-image-2'
| 'local-demo';
export type BabyLoveDrawingPoint = {
x: number;
y: number;
t: number;
};
export type BabyLoveDrawingStroke = {
strokeId: string;
tool: BabyLoveDrawingTool;
color: string;
points: BabyLoveDrawingPoint[];
};
export type BabyLoveDrawingRecord = {
drawingId: string;
templateId: BabyLoveDrawingTemplateId;
templateName: typeof BABY_LOVE_DRAWING_TEMPLATE_NAME;
originalImageSrc: string;
magicImageSrc: string | null;
strokeTrace: BabyLoveDrawingStroke[];
saveMode: BabyLoveDrawingSaveMode;
themeTags: string[];
createdAt: string;
updatedAt: string;
};
export type CreateBabyLoveDrawingMagicRequest = {
originalImageSrc: string;
strokeTrace: BabyLoveDrawingStroke[];
};
export type CreateBabyLoveDrawingMagicResponse = {
magicImageSrc: string;
generationProvider: BabyLoveDrawingGenerationProvider;
prompt: string;
};
export type SaveBabyLoveDrawingRequest = {
originalImageSrc: string;
magicImageSrc?: string | null;
strokeTrace: BabyLoveDrawingStroke[];
};
export type SaveBabyLoveDrawingResponse = {
record: BabyLoveDrawingRecord;
};
export const BABY_LOVE_DRAWING_RAINBOW_COLORS = [
{ id: 'red', label: '红', value: '#ef4444' },
{ id: 'orange', label: '橙', value: '#f97316' },
{ id: 'yellow', label: '黄', value: '#facc15' },
{ id: 'green', label: '绿', value: '#22c55e' },
{ id: 'cyan', label: '青', value: '#06b6d4' },
{ id: 'blue', label: '蓝', value: '#3b82f6' },
{ id: 'purple', label: '紫', value: '#a855f7' },
] as const;
export type BabyLoveDrawingRainbowColorId =
(typeof BABY_LOVE_DRAWING_RAINBOW_COLORS)[number]['id'];
export function normalizeBabyLoveDrawingTags(tags: string[]) {
return [
...new Set([
BABY_LOVE_DRAWING_EDUTAINMENT_TAG,
...tags.map((tag) => tag.trim()).filter(Boolean),
]),
];
}
@@ -1,121 +0,0 @@
export const BABY_OBJECT_MATCH_TEMPLATE_ID = 'baby-object-match';
export const BABY_OBJECT_MATCH_TEMPLATE_NAME = '宝贝识物';
export const BABY_OBJECT_MATCH_EDUTAINMENT_TAG = '寓教于乐';
export type BabyObjectMatchTemplateId = typeof BABY_OBJECT_MATCH_TEMPLATE_ID;
export type BabyObjectMatchAssetProvider =
| 'vector-engine-gpt-image-2'
| 'placeholder';
export type BabyObjectMatchPublicationStatus = 'draft' | 'published';
export type BabyObjectMatchItemAsset = {
itemId: string;
itemName: string;
imageSrc: string;
assetObjectId: string | null;
generationProvider: BabyObjectMatchAssetProvider;
prompt: string;
};
export type BabyObjectMatchVisualAssetKind =
| 'background'
| 'ui-frame'
| 'gift-box'
| 'basket'
| 'smoke-puff'
| 'left-hand'
| 'right-hand';
export type BabyObjectMatchVisualAsset = {
assetId: string;
assetKind: BabyObjectMatchVisualAssetKind;
imageSrc: string;
assetObjectId: string | null;
generationProvider: BabyObjectMatchAssetProvider;
prompt: string;
};
export type BabyObjectMatchVisualPackage = {
themePrompt: string;
assets: BabyObjectMatchVisualAsset[];
};
export type BabyObjectMatchDraft = {
draftId: string;
profileId: string;
templateId: BabyObjectMatchTemplateId;
templateName: typeof BABY_OBJECT_MATCH_TEMPLATE_NAME;
workTitle: string;
workDescription: string;
itemNames: [string, string];
itemAssets: [BabyObjectMatchItemAsset, BabyObjectMatchItemAsset];
visualPackage?: BabyObjectMatchVisualPackage | null;
themeTags: string[];
publicationStatus: BabyObjectMatchPublicationStatus;
createdAt: string;
updatedAt: string;
publishedAt: string | null;
};
export type CreateBabyObjectMatchDraftRequest = {
itemAName: string;
itemBName: string;
};
export type GenerateBabyObjectMatchAssetsRequest = {
itemNames: [string, string];
};
export type GenerateBabyObjectMatchAssetsResponse = {
assets: [BabyObjectMatchItemAsset, BabyObjectMatchItemAsset];
visualPackage?: BabyObjectMatchVisualPackage | null;
};
export type BabyObjectMatchDraftResponse = {
draft: BabyObjectMatchDraft;
};
export type SaveBabyObjectMatchDraftRequest = {
draft: BabyObjectMatchDraft;
};
export type BabyObjectMatchPublishRequest = {
draft: BabyObjectMatchDraft;
};
export type BabyObjectMatchPublishResponse = {
draft: BabyObjectMatchDraft;
publicWorkCode: string;
};
export function normalizeBabyObjectMatchItemName(value: string) {
return value.trim();
}
export function normalizeBabyObjectMatchTags(tags: string[]) {
return [
...new Set([
BABY_OBJECT_MATCH_EDUTAINMENT_TAG,
...tags.map((tag) => tag.trim()).filter(Boolean),
]),
];
}
export function hasBabyObjectMatchRequiredTag(tags: string[]) {
return tags.some((tag) => tag === BABY_OBJECT_MATCH_EDUTAINMENT_TAG);
}
export function validateBabyObjectMatchItemNames(
payload: CreateBabyObjectMatchDraftRequest,
) {
const itemAName = normalizeBabyObjectMatchItemName(payload.itemAName);
const itemBName = normalizeBabyObjectMatchItemName(payload.itemBName);
return {
itemAName,
itemBName,
valid: Boolean(itemAName && itemBName),
};
}
-9
View File
@@ -1,14 +1,5 @@
export type * from './barkBattle';
export type * from './creationAudio';
export type * from './creativeAgent';
export * from './editorAgent';
export type * from './editorAudio';
export * from './gameCreationApp';
export * from './hostBridge';
export type * from './hyper3d';
export * from './playTypes';
export type * from './publicWork';
export type * from './puzzleClear';
export type * from './puzzleCreativeTemplate';
export type * from './visualNovel';
export type * from './woodenFish';
-341
View File
@@ -1,341 +0,0 @@
import type { ExternalGenerationJobStatusRecord } from './externalGeneration';
export type JumpHopDifficulty = 'easy' | 'standard' | 'advanced' | 'challenge';
export type JumpHopStylePreset =
| 'minimal-blocks'
| 'paper-toy'
| 'neon-glass'
| 'forest-stone'
| 'future-metal'
| 'custom';
export type JumpHopGenerationStatus =
| 'draft'
| 'generating'
| 'ready'
| 'failed';
export type JumpHopTileType =
| 'start'
| 'normal'
| 'target'
| 'finish'
| 'bonus'
| 'accent';
export type JumpHopActionType =
| 'compile-draft'
| 'regenerate-tiles'
| 'update-work-meta'
| 'update-difficulty';
export type JumpHopRunStatus = 'playing' | 'failed' | 'cleared';
export type JumpHopJumpResult = 'miss' | 'hit' | 'perfect' | 'finish';
export interface JumpHopWorkspaceCreateRequest {
templateId: string;
themeText: string;
workTitle?: string;
workDescription?: string;
themeTags?: string[];
difficulty?: JumpHopDifficulty;
stylePreset?: JumpHopStylePreset;
characterPrompt?: string;
tilePrompt?: string;
endMoodPrompt?: string | null;
}
export interface JumpHopActionRequest {
actionType: JumpHopActionType;
profileId?: string | null;
themeText?: string | null;
workTitle?: string | null;
workDescription?: string | null;
themeTags?: string[] | null;
difficulty?: JumpHopDifficulty | null;
stylePreset?: JumpHopStylePreset | null;
characterPrompt?: string | null;
tilePrompt?: string | null;
endMoodPrompt?: string | null;
characterAsset?: JumpHopCharacterAsset | null;
tileAtlasAsset?: JumpHopCharacterAsset | null;
tileAssets?: JumpHopTileAsset[] | null;
coverComposite?: string | null;
backButtonAsset?: JumpHopCharacterAsset | null;
}
export interface JumpHopCharacterAsset {
assetId: string;
imageSrc: string;
imageObjectKey: string;
assetObjectId: string;
generationProvider: string;
prompt: string;
width: number;
height: number;
}
export interface JumpHopDefaultCharacter {
characterId: string;
displayName: string;
modelKind: 'builtin-three';
bodyColor: string;
accentColor: string;
}
export interface JumpHopTileAsset {
tileType: JumpHopTileType;
tileId?: string;
imageSrc: string;
imageObjectKey: string;
assetObjectId: string;
sourceAtlasCell: string;
atlasRow?: number;
atlasCol?: number;
visualWidth: number;
visualHeight: number;
topSurfaceRadius: number;
landingRadius: number;
faceAssets?: JumpHopTileFaceAssets | null;
}
export type JumpHopTileFaceKey =
| 'top'
| 'front'
| 'right'
| 'back'
| 'left'
| 'bottom';
export interface JumpHopTileFaceAsset {
face: JumpHopTileFaceKey;
assetId: string;
imageSrc: string;
imageObjectKey: string;
assetObjectId: string;
generationProvider: string;
prompt: string;
width: number;
height: number;
sourceAtlasCell: string;
}
export interface JumpHopTileFaceAssets {
top: JumpHopTileFaceAsset;
front: JumpHopTileFaceAsset;
right: JumpHopTileFaceAsset;
back: JumpHopTileFaceAsset;
left: JumpHopTileFaceAsset;
bottom: JumpHopTileFaceAsset;
}
export interface JumpHopScoring {
chargeToDistanceRatio: number;
maxChargeMs: number;
hitBonus: number;
perfectBonus: number;
}
export interface JumpHopPlatform {
platformId: string;
tileType: JumpHopTileType;
x: number;
y: number;
width: number;
height: number;
landingRadius: number;
perfectRadius: number;
scoreValue: number;
}
export interface JumpHopPath {
seed: string;
difficulty: JumpHopDifficulty;
platforms: JumpHopPlatform[];
finishIndex: number;
cameraPreset: string;
scoring: JumpHopScoring;
}
export interface JumpHopLastJump {
chargeMs: number;
jumpDistance: number;
targetPlatformIndex: number;
landedX: number;
landedY: number;
result: JumpHopJumpResult;
}
export interface JumpHopDraftResponse {
templateId: string;
templateName: string;
profileId: string | null;
themeText: string;
workTitle: string;
workDescription: string;
themeTags: string[];
difficulty: JumpHopDifficulty;
stylePreset: JumpHopStylePreset;
defaultCharacter?: JumpHopDefaultCharacter | null;
characterPrompt: string;
tilePrompt: string;
endMoodPrompt: string | null;
characterAsset: JumpHopCharacterAsset | null;
tileAtlasAsset: JumpHopCharacterAsset | null;
tileAssets: JumpHopTileAsset[];
path: JumpHopPath | null;
coverComposite: string | null;
backButtonAsset?: JumpHopCharacterAsset | null;
generationStatus: JumpHopGenerationStatus;
}
export interface JumpHopSessionSnapshotResponse {
sessionId: string;
ownerUserId: string;
status: JumpHopGenerationStatus;
draft: JumpHopDraftResponse | null;
createdAt: string;
updatedAt: string;
}
export interface JumpHopSessionResponse {
session: JumpHopSessionSnapshotResponse;
}
export interface JumpHopActionResponse {
actionType: JumpHopActionType;
session: JumpHopSessionSnapshotResponse;
work: JumpHopWorkProfileResponse | null;
queueState?: ExternalGenerationJobStatusRecord | null;
}
export interface JumpHopWorkSummaryResponse {
runtimeKind: 'jump-hop';
workId: string;
profileId: string;
ownerUserId: string;
sourceSessionId: string | null;
themeText: string;
workTitle: string;
workDescription: string;
themeTags: string[];
difficulty: JumpHopDifficulty;
stylePreset: JumpHopStylePreset;
coverImageSrc: string | null;
publicationStatus: string;
playCount: number;
updatedAt: string;
publishedAt: string | null;
publishReady: boolean;
generationStatus: JumpHopGenerationStatus;
}
export interface JumpHopWorkProfileResponse {
summary: JumpHopWorkSummaryResponse;
draft: JumpHopDraftResponse;
path: JumpHopPath;
defaultCharacter?: JumpHopDefaultCharacter | null;
characterAsset: JumpHopCharacterAsset;
tileAtlasAsset: JumpHopCharacterAsset;
tileAssets: JumpHopTileAsset[];
backButtonAsset?: JumpHopCharacterAsset | null;
}
export interface JumpHopWorksResponse {
items: JumpHopWorkSummaryResponse[];
}
export interface JumpHopWorkDetailResponse {
item: JumpHopWorkProfileResponse;
}
export interface JumpHopWorkMutationResponse {
item: JumpHopWorkProfileResponse;
}
export interface JumpHopGalleryCardResponse {
publicWorkCode: string;
workId: string;
profileId: string;
ownerUserId: string;
authorDisplayName: string;
themeText: string;
workTitle: string;
workDescription: string;
coverImageSrc: string | null;
themeTags: string[];
difficulty: JumpHopDifficulty;
stylePreset: JumpHopStylePreset;
publicationStatus: string;
playCount: number;
updatedAt: string;
publishedAt: string | null;
generationStatus: JumpHopGenerationStatus;
}
export interface JumpHopGalleryResponse {
items: JumpHopGalleryCardResponse[];
hasMore: boolean;
nextCursor: string | null;
}
export interface JumpHopGalleryDetailResponse {
item: JumpHopWorkProfileResponse;
}
export interface JumpHopRuntimeRunSnapshotResponse {
runId: string;
profileId: string;
ownerUserId: string;
status: JumpHopRunStatus;
currentPlatformIndex: number;
successfulJumpCount: number;
durationMs: number;
score: number;
combo: number;
path: JumpHopPath;
lastJump: JumpHopLastJump | null;
startedAtMs: number;
finishedAtMs: number | null;
}
export interface JumpHopRunResponse {
run: JumpHopRuntimeRunSnapshotResponse;
}
export interface JumpHopStartRunRequest {
profileId: string;
runtimeMode?: 'draft' | 'published';
}
export interface JumpHopJumpRequest {
dragDistance: number;
dragVectorX?: number;
dragVectorY?: number;
clientEventId: string;
}
export interface JumpHopRestartRunRequest {
clientActionId: string;
}
export interface JumpHopJumpResponse {
run: JumpHopRuntimeRunSnapshotResponse;
}
export interface JumpHopLeaderboardEntry {
rank: number;
playerId: string;
displayName: string;
successfulJumpCount: number;
durationMs: number;
updatedAt: string;
}
export interface JumpHopLeaderboardResponse {
profileId: string;
items: JumpHopLeaderboardEntry[];
viewerBest?: JumpHopLeaderboardEntry | null;
}
@@ -1,151 +0,0 @@
/**
* 抓大鹅 Match3D 创作 Agent 共享契约。
* 字段按 HTTP facade 的 camelCase DTO 命名,后端领域层 snake_case 字段由 facade 映射。
*/
import type {
Match3DGeneratedBackgroundAsset,
Match3DGeneratedItemAsset,
} from './match3dWorks';
export type Match3DCreationStage =
| 'collecting'
| 'collecting_config'
| 'ready_to_compile'
| 'draft_ready'
| 'draft_compiled'
| 'ready_to_publish'
| 'published'
| string;
export type Match3DAgentMessageRole = 'user' | 'assistant' | 'system' | string;
export type Match3DAgentMessageKind =
| 'chat'
| 'summary'
| 'action_result'
| 'warning'
| string;
export type Match3DAnchorStatus =
| 'confirmed'
| 'missing'
| 'inferred'
| 'locked'
| string;
export interface CreateMatch3DAgentSessionRequest {
seedText?: string;
themeText?: string;
referenceImageSrc?: string | null;
clearCount?: number;
difficulty?: number;
assetStyleId?: string | null;
assetStyleLabel?: string | null;
assetStylePrompt?: string | null;
generateClickSound?: boolean;
}
export type CreateMatch3DSessionRequest = CreateMatch3DAgentSessionRequest;
export interface SendMatch3DAgentMessageRequest {
clientMessageId: string;
text: string;
quickFillRequested?: boolean;
referenceImageSrc?: string | null;
}
export type SendMatch3DMessageRequest = SendMatch3DAgentMessageRequest;
export interface ExecuteMatch3DAgentActionRequest {
action: string;
gameName?: string;
summary?: string;
tags?: string[];
coverImageSrc?: string | null;
clearCount?: number;
difficulty?: number;
generateClickSound?: boolean;
}
export type ExecuteMatch3DActionRequest = ExecuteMatch3DAgentActionRequest;
export interface Match3DAnchorItemResponse {
key: string;
label: string;
value: string;
status: Match3DAnchorStatus;
}
export interface Match3DAnchorPackResponse {
theme: Match3DAnchorItemResponse;
clearCount: Match3DAnchorItemResponse;
difficulty: Match3DAnchorItemResponse;
}
export interface Match3DCreatorConfig {
themeText: string;
referenceImageSrc?: string | null;
clearCount: number;
difficulty: number;
assetStyleId?: string | null;
assetStyleLabel?: string | null;
assetStylePrompt?: string | null;
generateClickSound?: boolean;
}
export interface Match3DResultDraft {
profileId: string;
gameName: string;
themeText: string;
summaryText?: string;
summary?: string;
tags: string[];
coverImageSrc?: string | null;
referenceImageSrc?: string | null;
clearCount: number;
difficulty: number;
totalItemCount?: number;
publishReady?: boolean;
blockers?: string[];
backgroundPrompt?: string | null;
backgroundImageSrc?: string | null;
backgroundImageObjectKey?: string | null;
generatedBackgroundAsset?: Match3DGeneratedBackgroundAsset | null;
generatedItemAssets?: Match3DGeneratedItemAsset[];
}
export interface Match3DAgentMessage {
id: string;
role: Match3DAgentMessageRole;
kind: Match3DAgentMessageKind;
text: string;
createdAt: string;
}
export type Match3DAgentMessageResponse = Match3DAgentMessage;
export interface Match3DAgentSessionSnapshot {
sessionId: string;
currentTurn: number;
progressPercent: number;
stage: Match3DCreationStage;
anchorPack: Match3DAnchorPackResponse;
config?: Match3DCreatorConfig | null;
draft?: Match3DResultDraft | null;
messages: Match3DAgentMessage[];
lastAssistantReply?: string | null;
publishedProfileId?: string | null;
updatedAt: string;
}
export interface Match3DAgentSessionResponse {
session: Match3DAgentSessionSnapshot;
}
export type Match3DSessionResponse = Match3DAgentSessionResponse;
export interface Match3DAgentActionResponse {
session: Match3DAgentSessionSnapshot;
}
export type Match3DActionResponse = Match3DAgentActionResponse;
@@ -1,130 +0,0 @@
/**
* 抓大鹅 Match3D 运行态共享契约。
* 前端可以使用 Flying 做即时表现;后端权威快照只应返回 InBoard、InTray、Cleared。
*/
export type Match3DRunStatus =
| 'running'
| 'won'
| 'failed'
| 'stopped'
| 'Running'
| 'Won'
| 'Failed'
| 'Stopped'
| string;
export type Match3DItemState =
| 'in_board'
| 'in_tray'
| 'cleared'
| 'InBoard'
| 'Flying'
| 'InTray'
| 'Cleared'
| string;
export type Match3DFailureReason =
| 'time_up'
| 'tray_full'
| 'TimeUp'
| 'TrayFull'
| string;
export type Match3DClickRejectReason =
| 'run_not_active'
| 'snapshot_version_mismatch'
| 'item_not_found'
| 'item_not_in_board'
| 'item_not_clickable'
| 'tray_full'
| string;
export type Match3DClickConfirmStatus =
| 'Accepted'
| 'RejectedNotClickable'
| 'RejectedAlreadyMoved'
| 'RejectedTrayFull'
| 'VersionConflict'
| 'RunFinished';
export interface StartMatch3DRunRequest {
profileId: string;
itemTypeCountOverride?: number | null;
}
export interface Match3DClickItemRequest {
runId?: string;
itemInstanceId: string;
clientActionId?: string;
snapshotVersion?: number;
clientSnapshotVersion: number;
clientEventId: string;
clickedAtMs: number;
}
export type ClickMatch3DItemRequest = Match3DClickItemRequest;
export interface StopMatch3DRunRequest {
clientActionId: string;
}
export interface Match3DItemSnapshot {
itemInstanceId: string;
itemTypeId: string;
visualKey: string;
x: number;
y: number;
radius: number;
layer: number;
state: Match3DItemState;
clickable: boolean;
traySlotIndex?: number | null;
}
export interface Match3DTraySlot {
slotIndex: number;
itemInstanceId?: string | null;
itemTypeId?: string | null;
visualKey?: string | null;
}
export interface Match3DRunSnapshot {
runId: string;
profileId: string;
ownerUserId?: string;
status: Match3DRunStatus;
snapshotVersion: number;
startedAtMs: number;
durationLimitMs: number;
serverNowMs?: number;
remainingMs: number;
clearCount: number;
totalItemCount: number;
clearedItemCount: number;
boardVersion?: number;
items: Match3DItemSnapshot[];
traySlots: Match3DTraySlot[];
failureReason?: Match3DFailureReason | null;
lastConfirmedActionId?: string | null;
}
export interface Match3DClickConfirmation {
accepted: boolean;
rejectReason?: Match3DClickRejectReason | null;
enteredSlotIndex?: number | null;
clearedItemInstanceIds: string[];
run: Match3DRunSnapshot;
}
export interface Match3DClickItemResult {
status: Match3DClickConfirmStatus;
run: Match3DRunSnapshot;
acceptedItemInstanceId?: string;
clearedItemInstanceIds: string[];
failureReason?: Match3DFailureReason | null;
}
export interface Match3DRunResponse {
run: Match3DRunSnapshot;
}
export interface Match3DClickResponse {
confirmation: Match3DClickConfirmation;
}
@@ -1,200 +0,0 @@
/**
* 抓大鹅 Match3D 作品读写共享契约。
* 首版作品发布必须补齐游戏名称、标签、封面、题材、消除次数和难度。
*/
import type { CreationAudioAsset } from './creationAudio';
export type Match3DWorkPublicationStatus = 'draft' | 'published' | string;
export type Match3DWorkGenerationStatus =
| 'idle'
| 'generating'
| 'ready'
| string;
export type Match3DGeneratedItemAssetStatus =
| 'pending'
| 'image_ready'
| 'model_generating'
| 'model_ready'
| 'failed'
| string;
export type Match3DGeneratedItemSize = '大' | '中' | '小' | string;
export interface Match3DGeneratedBackgroundAsset {
prompt: string;
levelScenePrompt?: string | null;
levelSceneImageSrc?: string | null;
levelSceneImageObjectKey?: string | null;
imageSrc?: string | null;
imageObjectKey?: string | null;
uiSpritesheetPrompt?: string | null;
uiSpritesheetImageSrc?: string | null;
uiSpritesheetImageObjectKey?: string | null;
itemSpritesheetPrompt?: string | null;
itemSpritesheetImageSrc?: string | null;
itemSpritesheetImageObjectKey?: string | null;
containerPrompt?: string | null;
containerImageSrc?: string | null;
containerImageObjectKey?: string | null;
status: string;
error?: string | null;
}
export interface Match3DGeneratedItemImageView {
viewId: string;
viewIndex: number;
imageSrc?: string | null;
imageObjectKey?: string | null;
}
export interface Match3DGeneratedItemAsset {
itemId: string;
itemName: string;
itemSize?: Match3DGeneratedItemSize | null;
imageSrc?: string | null;
imageObjectKey?: string | null;
imageViews?: Match3DGeneratedItemImageView[];
modelSrc?: string | null;
modelObjectKey?: string | null;
modelFileName?: string | null;
taskUuid?: string | null;
subscriptionKey?: string | null;
soundPrompt?: string | null;
backgroundMusicTitle?: string | null;
backgroundMusicStyle?: string | null;
backgroundMusicPrompt?: string | null;
backgroundMusic?: CreationAudioAsset | null;
clickSound?: CreationAudioAsset | null;
backgroundAsset?: Match3DGeneratedBackgroundAsset | null;
status: Match3DGeneratedItemAssetStatus;
error?: string | null;
}
export interface PutMatch3DAudioAssetsRequest {
generatedItemAssets: Match3DGeneratedItemAsset[];
}
export interface PersistMatch3DGeneratedModelRequest {
itemId: string;
itemName: string;
sourceUrl: string;
fileName?: string | null;
taskUuid?: string | null;
subscriptionKey?: string | null;
}
export interface PersistMatch3DGeneratedModelResponse {
asset: Match3DGeneratedItemAsset;
}
export interface GenerateMatch3DCoverImageRequest {
prompt: string;
uploadedImageSrc?: string | null;
referenceImageSrc?: string | null;
referenceImageSrcs?: string[];
}
export interface GenerateMatch3DCoverImageResponse {
item: Match3DWorkProfile;
coverImageSrc: string;
coverImageObjectKey: string;
prompt: string;
}
export interface GenerateMatch3DBackgroundImageRequest {
prompt: string;
}
export interface GenerateMatch3DBackgroundImageResponse {
item: Match3DWorkProfile;
backgroundImageSrc: string;
backgroundImageObjectKey: string;
generatedBackgroundAsset: Match3DGeneratedBackgroundAsset;
prompt: string;
}
export interface GenerateMatch3DContainerImageRequest {
prompt: string;
}
export interface GenerateMatch3DContainerImageResponse {
item: Match3DWorkProfile;
containerImageSrc: string;
containerImageObjectKey: string;
generatedBackgroundAsset: Match3DGeneratedBackgroundAsset;
prompt: string;
}
export type GenerateMatch3DItemAssetsMode = 'append' | 'replace';
export interface GenerateMatch3DItemAssetsRequest {
itemNames: string[];
mode?: GenerateMatch3DItemAssetsMode;
}
export interface GenerateMatch3DItemAssetsResponse {
item: Match3DWorkProfile;
generatedItemAssets: Match3DGeneratedItemAsset[];
}
export interface PutMatch3DWorkRequest {
gameName: string;
themeText?: string;
summary: string;
tags: string[];
coverImageSrc?: string | null;
referenceImageSrc?: string | null;
clearCount: number;
difficulty: number;
}
export interface GenerateMatch3DWorkTagsRequest {
gameName: string;
themeText: string;
summary?: string | null;
}
export interface GenerateMatch3DWorkTagsResponse {
tags: string[];
}
export interface Match3DWorkSummary {
workId: string;
profileId: string;
ownerUserId: string;
sourceSessionId?: string | null;
gameName: string;
themeText: string;
summary: string;
tags: string[];
coverImageSrc?: string | null;
referenceImageSrc?: string | null;
clearCount: number;
difficulty: number;
publicationStatus: Match3DWorkPublicationStatus;
playCount: number;
updatedAt: string;
publishedAt?: string | null;
publishReady: boolean;
generationStatus?: Match3DWorkGenerationStatus | null;
backgroundPrompt?: string | null;
backgroundImageSrc?: string | null;
backgroundImageObjectKey?: string | null;
generatedBackgroundAsset?: Match3DGeneratedBackgroundAsset | null;
generatedItemAssets?: Match3DGeneratedItemAsset[];
}
export interface Match3DWorkProfile extends Match3DWorkSummary {}
export interface Match3DWorksResponse {
items: Match3DWorkSummary[];
}
export interface Match3DWorkDetailResponse {
item: Match3DWorkProfile;
}
export interface Match3DWorkMutationResponse {
item: Match3DWorkProfile;
}
@@ -1,74 +0,0 @@
export const PLATFORM_CREATION_TYPE_IDS = [
'rpg',
'big-fish',
'puzzle',
'puzzle-clear',
'match3d',
'jump-hop',
'wooden-fish',
'square-hole',
'bark-battle',
'visual-novel',
'baby-object-match',
'creative-agent',
'airp',
] as const;
export type PlatformCreationTypeId =
(typeof PLATFORM_CREATION_TYPE_IDS)[number];
const PLATFORM_CREATION_TYPE_ID_SET: ReadonlySet<string> = new Set(
PLATFORM_CREATION_TYPE_IDS,
);
export function isPlatformCreationTypeId(
value: string,
): value is PlatformCreationTypeId {
return PLATFORM_CREATION_TYPE_ID_SET.has(value);
}
export function assertPlatformCreationTypeId(
value: string,
): PlatformCreationTypeId {
if (isPlatformCreationTypeId(value)) {
return value;
}
throw new Error(`未知创作类型:${value}`);
}
export const PUBLIC_WORK_SOURCE_TYPES = [
'custom-world',
'big-fish',
'puzzle',
'puzzle-clear',
'jump-hop',
'wooden-fish',
'match3d',
'square-hole',
'visual-novel',
'bark-battle',
'edutainment',
] as const;
export type PublicWorkSourceType = (typeof PUBLIC_WORK_SOURCE_TYPES)[number];
const PUBLIC_WORK_SOURCE_TYPE_SET: ReadonlySet<string> = new Set(
PUBLIC_WORK_SOURCE_TYPES,
);
export function isPublicWorkSourceType(
value: string,
): value is PublicWorkSourceType {
return PUBLIC_WORK_SOURCE_TYPE_SET.has(value);
}
export function assertPublicWorkSourceType(
value: string,
): PublicWorkSourceType {
if (isPublicWorkSourceType(value)) {
return value;
}
throw new Error(`未知公开作品类型:${value}`);
}
@@ -1,40 +0,0 @@
import type { PublicWorkSourceType } from './playTypes';
export interface PublicWorkGalleryEntryResponse {
sourceType: PublicWorkSourceType;
workId: string;
profileId: string;
sourceSessionId?: string | null;
publicWorkCode: string;
ownerUserId: string;
authorDisplayName: string;
worldName: string;
subtitle: string;
summaryText: string;
coverImageSrc?: string | null;
coverAssetId?: string | null;
themeTags: string[];
playCount: number;
remixCount: number;
likeCount: number;
recentPlayCount7d?: number;
publishedAt?: string | null;
updatedAt: string;
sortTimeMicros: number;
}
export interface PublicWorkDetailEntryResponse
extends PublicWorkGalleryEntryResponse {
detailPayloadJson: string;
}
export interface PublicWorkGalleryResponse {
items: PublicWorkGalleryEntryResponse[];
hasMore?: boolean;
nextCursor?: string | null;
totalCount?: number;
}
export interface PublicWorkDetailResponse {
item: PublicWorkDetailEntryResponse;
}
@@ -1,134 +0,0 @@
import type { ExternalGenerationJobStatusRecord } from './externalGeneration';
import type { PuzzleAgentSessionSnapshot } from './puzzleAgentSession';
export type PuzzleAgentSuggestedActionType =
| 'request_summary'
| 'compile_puzzle_draft'
| 'generate_puzzle_images'
| 'generate_puzzle_ui_background'
| 'generate_puzzle_tags'
| 'publish_puzzle_work';
export interface PuzzleAgentSuggestedAction {
id: string;
actionType: PuzzleAgentSuggestedActionType;
label: string;
}
export type PuzzleAgentActionType =
| 'save_puzzle_form_draft'
| 'compile_puzzle_draft'
| 'generate_puzzle_images'
| 'generate_puzzle_ui_background'
| 'generate_puzzle_tags'
| 'select_puzzle_image'
| 'publish_puzzle_work';
export type PuzzleAgentOperationType =
| 'process_message'
| PuzzleAgentActionType;
export type PuzzleAgentOperationStatus =
| 'queued'
| 'running'
| 'completed'
| 'failed';
export interface PuzzleAgentOperationRecord {
operationId: string;
type: PuzzleAgentOperationType;
status: PuzzleAgentOperationStatus;
phaseLabel: string;
phaseDetail: string;
progress: number;
error?: string | null;
queueState?: ExternalGenerationJobStatusRecord | null;
}
export type PuzzleAgentActionRequest =
| {
action: 'save_puzzle_form_draft';
promptText?: string | null;
workTitle?: string;
workDescription?: string;
pictureDescription?: string;
referenceImageSrc?: string | null;
referenceImageSrcs?: string[];
referenceImageAssetObjectId?: string | null;
referenceImageAssetObjectIds?: string[];
imageModel?: string | null;
aiRedraw?: boolean;
}
| {
action: 'compile_puzzle_draft';
promptText?: string | null;
workTitle?: string;
workDescription?: string;
pictureDescription?: string;
referenceImageSrc?: string | null;
referenceImageSrcs?: string[];
referenceImageAssetObjectId?: string | null;
referenceImageAssetObjectIds?: string[];
imageModel?: string | null;
aiRedraw?: boolean;
candidateCount?: number;
}
| {
action: 'generate_puzzle_images';
levelId?: string | null;
promptText?: string | null;
referenceImageSrc?: string | null;
referenceImageSrcs?: string[];
referenceImageAssetObjectId?: string | null;
referenceImageAssetObjectIds?: string[];
imageModel?: string | null;
aiRedraw?: boolean;
candidateCount?: number;
shouldAutoNameLevel?: boolean;
workTitle?: string;
workDescription?: string;
summary?: string;
themeTags?: string[];
levelsJson?: string;
}
| {
action: 'generate_puzzle_ui_background';
levelId?: string | null;
promptText: string;
workTitle?: string;
workDescription?: string;
summary?: string;
themeTags?: string[];
levelsJson?: string;
}
| {
action: 'generate_puzzle_tags';
workTitle: string;
workDescription: string;
levelName?: string;
summary?: string;
themeTags?: string[];
levelsJson?: string;
}
| {
action: 'select_puzzle_image';
levelId?: string | null;
candidateId: string;
}
| {
action: 'publish_puzzle_work';
workTitle?: string;
workDescription?: string;
levelName?: string;
summary?: string;
themeTags?: string[];
levelsJson?: string;
};
/**
* 拼图操作接口直接返回最新会话,避免前端在选图等轻操作后再额外 GET 大体积快照。
*/
export interface PuzzleAgentActionResponse {
operation: PuzzleAgentOperationRecord;
session: PuzzleAgentSessionSnapshot;
}
@@ -1,89 +0,0 @@
import type { JsonObject } from './common';
import type { CreationAudioAsset } from './creationAudio';
export type PuzzleAnchorStatus =
| 'missing'
| 'inferred'
| 'confirmed'
| 'locked';
export interface PuzzleAnchorItem {
key: string;
label: string;
value: string;
status: PuzzleAnchorStatus;
}
export interface PuzzleAnchorPack {
themePromise: PuzzleAnchorItem;
visualSubject: PuzzleAnchorItem;
visualMood: PuzzleAnchorItem;
compositionHooks: PuzzleAnchorItem;
tagsAndForbidden: PuzzleAnchorItem;
}
export interface PuzzleCreatorIntent {
sourceMode: 'agent_chat' | 'form';
rawMessagesSummary: string;
themePromise: string;
visualSubject: string;
visualMood: string[];
compositionHooks: string[];
themeTags: string[];
forbiddenDirectives: string[];
}
export interface PuzzleGeneratedImageCandidate {
candidateId: string;
imageSrc: string;
assetId: string;
prompt: string;
actualPrompt?: string | null;
sourceType: 'generated' | 'uploaded';
selected: boolean;
}
export interface PuzzleDraftLevel {
levelId: string;
levelName: string;
pictureDescription: string;
pictureReference?: string | null;
uiBackgroundPrompt?: string | null;
uiBackgroundImageSrc?: string | null;
uiBackgroundImageObjectKey?: string | null;
levelSceneImageSrc?: string | null;
levelSceneImageObjectKey?: string | null;
uiSpritesheetImageSrc?: string | null;
uiSpritesheetImageObjectKey?: string | null;
levelBackgroundImageSrc?: string | null;
levelBackgroundImageObjectKey?: string | null;
backgroundMusic?: CreationAudioAsset | null;
candidates: PuzzleGeneratedImageCandidate[];
selectedCandidateId: string | null;
coverImageSrc: string | null;
coverAssetId: string | null;
generationStatus: 'idle' | 'generating' | 'ready' | 'failed';
}
export interface PuzzleResultDraft {
workTitle?: string;
workDescription?: string;
levelName: string;
summary: string;
themeTags: string[];
forbiddenDirectives: string[];
creatorIntent: PuzzleCreatorIntent | null;
anchorPack: PuzzleAnchorPack;
candidates: PuzzleGeneratedImageCandidate[];
selectedCandidateId: string | null;
coverImageSrc: string | null;
coverAssetId: string | null;
generationStatus: 'idle' | 'generating' | 'ready' | 'failed';
levels?: PuzzleDraftLevel[];
formDraft?: {
workTitle?: string;
workDescription?: string;
pictureDescription?: string;
} | null;
metadata?: JsonObject | null;
}

Some files were not shown because too many files have changed in this diff Show More