import type { CreatePuzzleAgentSessionRequest, PuzzleAgentSessionSnapshot, } from '../../../packages/shared/src/contracts/puzzleAgentSession'; import { createMiniGameDraftGenerationState, type MiniGameDraftGenerationKind, type MiniGameDraftGenerationPhase, type MiniGameDraftGenerationState, resolveMiniGameDraftGenerationStartedAtMs, } from '../../services/miniGameDraftGenerationProgress'; export function createMiniGameDraftGenerationStateForRestoredDraft( kind: MiniGameDraftGenerationKind, metadata?: MiniGameDraftGenerationState['metadata'], startedAtMs = Date.now(), ): MiniGameDraftGenerationState { return { ...createMiniGameDraftGenerationState(kind, startedAtMs), ...(metadata ? { metadata } : {}), }; } export function createFailedMiniGameDraftGenerationStateForRestoredDraft( kind: MiniGameDraftGenerationKind, updatedAt: string | null | undefined, error: string, metadata?: MiniGameDraftGenerationState['metadata'], ): MiniGameDraftGenerationState { return resolveFinishedMiniGameDraftGenerationState( createMiniGameDraftGenerationStateForRestoredDraft( kind, metadata, resolveMiniGameDraftGenerationStartedAtMs(updatedAt), ), 'failed', { error }, ); } /** 清理生成态完成时间,避免返回生成页后继续沿用结束态计时。 */ export function rebaseMiniGameDraftGenerationStateForDisplay( state: MiniGameDraftGenerationState, ): MiniGameDraftGenerationState { return { ...state, finishedAtMs: undefined, }; } export function rebaseMiniGameDraftBackgroundCompileTaskForDisplay< T extends { generationState: MiniGameDraftGenerationState }, >(task: T): T { return { ...task, generationState: rebaseMiniGameDraftGenerationStateForDisplay( task.generationState, ), }; } export function createPuzzleDraftGenerationStateFromPayload( payload: CreatePuzzleAgentSessionRequest | null | undefined, session: PuzzleAgentSessionSnapshot | null | undefined = null, ): MiniGameDraftGenerationState { const puzzleProgressPercent = session?.draft && !session.draft.formDraft ? session.progressPercent : undefined; return { ...createMiniGameDraftGenerationState( 'puzzle', resolveMiniGameDraftGenerationStartedAtMs(session?.updatedAt), ), metadata: { puzzleAiRedraw: payload?.aiRedraw ?? true, puzzleActivePhaseId: typeof puzzleProgressPercent === 'number' ? 'compile' : undefined, puzzleActiveStepStartedAtMs: typeof puzzleProgressPercent === 'number' ? Date.now() : undefined, puzzleProgressPercent, }, }; } export function resolvePuzzlePhaseFromSessionProgress( state: MiniGameDraftGenerationState, session: PuzzleAgentSessionSnapshot, ): MiniGameDraftGenerationPhase { if (session.progressPercent >= 96) { return 'puzzle-select-image'; } if (session.progressPercent >= 94) { return 'puzzle-ui-assets'; } if (session.progressPercent >= 88) { return state.metadata?.puzzleAiRedraw === false ? 'puzzle-level-scene' : 'puzzle-cover-image'; } return 'compile'; } export function mergePuzzleSessionProgressIntoGenerationState( state: MiniGameDraftGenerationState, session: PuzzleAgentSessionSnapshot, ): MiniGameDraftGenerationState { const isCompiledGenerationSession = Boolean( session.draft && !session.draft.formDraft, ); const nextPhaseId = isCompiledGenerationSession ? resolvePuzzlePhaseFromSessionProgress(state, session) : state.metadata?.puzzleActivePhaseId; const shouldResetActiveStepStart = isCompiledGenerationSession && nextPhaseId != null && nextPhaseId !== state.metadata?.puzzleActivePhaseId; return { ...state, metadata: { ...state.metadata, puzzleActivePhaseId: nextPhaseId, puzzleActiveStepStartedAtMs: shouldResetActiveStepStart ? resolveMiniGameDraftGenerationStartedAtMs(session.updatedAt) : state.metadata?.puzzleActiveStepStartedAtMs, puzzleProgressPercent: isCompiledGenerationSession ? session.progressPercent : state.metadata?.puzzleProgressPercent, }, }; } export function resolveFinishedMiniGameDraftGenerationState( state: MiniGameDraftGenerationState, phase: 'ready' | 'failed', options: { error?: string | null; completedAssetCount?: number; totalAssetCount?: number; } = {}, ): MiniGameDraftGenerationState { return { ...state, phase, finishedAtMs: Date.now(), error: options.error ?? state.error, completedAssetCount: options.completedAssetCount ?? state.completedAssetCount, totalAssetCount: options.totalAssetCount ?? state.totalAssetCount, }; } export function isMiniGameDraftReady( state: MiniGameDraftGenerationState | null, ) { return state?.phase === 'ready'; } export function isMiniGameDraftGenerating( state: MiniGameDraftGenerationState | null, ) { return Boolean(state && state.phase !== 'ready' && state.phase !== 'failed'); }