import type { RpgCreationPreviewSource } from '../../../packages/shared/src/contracts/rpgCreationPreview'; import type { CustomWorldProfile } from '../../types'; export type PlatformRpgAgentResultBlockerView = { code?: string | null; message: string; }; export type PlatformRpgAgentResultPublishGateView = { blockers: string[]; publishReady: boolean; }; const AGENT_RESULT_STRUCTURAL_BLOCKER_CODES = new Set([ 'publish_missing_world_hook', 'publish_missing_player_premise', 'publish_missing_core_conflict', 'publish_missing_main_chapter', 'publish_missing_first_act', ]); function readProfileTextField( profile: CustomWorldProfile | null, paths: string[], ) { for (const path of paths) { let current: unknown = profile; for (const segment of path.split('.')) { if (!current || typeof current !== 'object') { current = null; break; } current = (current as Record)[segment]; } if (typeof current === 'string' && current.trim()) { return current.trim(); } } return null; } function hasProfileTextArray(profile: CustomWorldProfile | null, key: string) { const value = profile ? (profile as unknown as Record)[key] : null; return Array.isArray(value) ? value.some((entry) => typeof entry === 'string' && entry.trim()) : false; } function hasProfileArray(profile: CustomWorldProfile | null, key: string) { const value = profile ? (profile as unknown as Record)[key] : null; return Array.isArray(value) && value.length > 0; } function hasSceneAct(profile: CustomWorldProfile | null) { const rawProfile = profile as unknown as Record | null; const chapters = rawProfile && (Array.isArray(rawProfile.sceneChapterBlueprints) ? rawProfile.sceneChapterBlueprints : Array.isArray(rawProfile.sceneChapters) ? rawProfile.sceneChapters : []); return Array.isArray(chapters) ? chapters.some((chapter) => { const acts = chapter && typeof chapter === 'object' ? (chapter as Record).acts : null; return Array.isArray(acts) && acts.length > 0; }) : false; } function isAgentResultStructuralBlockerResolved( profile: CustomWorldProfile, code: string | null | undefined, ) { if (!code || !AGENT_RESULT_STRUCTURAL_BLOCKER_CODES.has(code)) { return false; } if (code === 'publish_missing_world_hook') { return Boolean( readProfileTextField(profile, [ 'worldHook', 'creatorIntent.worldHook', 'anchorContent.worldPromise', 'anchorContent.worldPromise.hook', 'settingText', ]), ); } if (code === 'publish_missing_player_premise') { return Boolean( readProfileTextField(profile, [ 'playerPremise', 'creatorIntent.playerPremise', 'anchorContent.playerEntryPoint', 'anchorContent.playerEntryPoint.openingIdentity', 'anchorContent.playerEntryPoint.openingProblem', 'anchorContent.playerEntryPoint.entryMotivation', ]), ); } if (code === 'publish_missing_core_conflict') { return hasProfileTextArray(profile, 'coreConflicts'); } if (code === 'publish_missing_main_chapter') { return ( hasProfileArray(profile, 'chapters') || hasProfileArray(profile, 'sceneChapterBlueprints') || hasProfileArray(profile, 'sceneChapters') ); } return hasSceneAct(profile); } export function buildPlatformRpgAgentResultPublishGateView( profile: CustomWorldProfile | null, fallbackBlockers: PlatformRpgAgentResultBlockerView[], fallbackPublishReady: boolean, ): PlatformRpgAgentResultPublishGateView { if (!profile) { return { blockers: fallbackBlockers.map((entry) => entry.message), publishReady: fallbackPublishReady, }; } const blockers = fallbackBlockers .filter( (entry) => !isAgentResultStructuralBlockerResolved(profile, entry.code), ) .map((entry) => entry.message); return { blockers, publishReady: blockers.length === 0, }; } export function resolvePlatformRpgAgentResultPreviewSourceLabel( source: RpgCreationPreviewSource | string | null | undefined, ) { if (!source) { return null; } if (source === 'published_profile') { return '已发布世界'; } if (source === 'session_preview') { return '会话预览'; } return '服务端预览'; }