import type { JsonObject } from './common'; import type { AdminUpsertProfileMembershipPlanRequest } from './generated/AdminUpsertProfileMembershipPlanRequest'; import type { ProfileDailyFreePointsResponse } from './generated/ProfileDailyFreePointsResponse'; import type { ProfileMembershipChangeKindToken } from './generated/ProfileMembershipChangeKindToken'; import type { ProfileMembershipCycleKindToken } from './generated/ProfileMembershipCycleKindToken'; import type { ProfileMembershipModelAccessToken } from './generated/ProfileMembershipModelAccessToken'; import type { ProfileMembershipPlanAdminListResponse } from './generated/ProfileMembershipPlanAdminListResponse'; import type { ProfileMembershipPlanResponse } from './generated/ProfileMembershipPlanResponse'; import type { ProfileMembershipPlanToken } from './generated/ProfileMembershipPlanToken'; import type { ProfileMembershipResponse } from './generated/ProfileMembershipResponse'; import type { ProfileMembershipStatusToken } from './generated/ProfileMembershipStatusToken'; import type { ProfileMembershipUpgradeQuoteRequest } from './generated/ProfileMembershipUpgradeQuoteRequest'; import type { ProfileMembershipUpgradeQuoteResponse } from './generated/ProfileMembershipUpgradeQuoteResponse'; import type { ProfileMudPointBalanceResponse as ProfileMudPointBalance } from './generated/ProfileMudPointBalanceResponse'; import type { ProfileRechargeCenterResponse as GeneratedProfileRechargeCenterResponse } from './generated/ProfileRechargeCenterResponse'; import type { ProfileRechargeOrderResponse } from './generated/ProfileRechargeOrderResponse'; import type { ProfileRechargeProductResponse } from './generated/ProfileRechargeProductResponse'; export type { AdminUpsertProfileMembershipPlanRequest, ProfileDailyFreePointsResponse, ProfileMembershipChangeKindToken, ProfileMembershipCycleKindToken, ProfileMembershipModelAccessToken, ProfileMembershipPlanAdminListResponse, ProfileMembershipPlanResponse, ProfileMembershipPlanToken, ProfileMembershipResponse, ProfileMembershipStatusToken, ProfileMembershipUpgradeQuoteRequest, ProfileMembershipUpgradeQuoteResponse, ProfileMudPointBalance, ProfileRechargeOrderResponse, ProfileRechargeProductResponse, }; export const SAVE_SNAPSHOT_VERSION = 2; export const DEFAULT_MUSIC_VOLUME = 0.42; export const DEFAULT_PLATFORM_THEME = 'light'; export const PLATFORM_THEMES = ['light', 'dark'] as const; export type PlatformTheme = (typeof PLATFORM_THEMES)[number]; export type SavedGameSnapshot< TGameState = unknown, TBottomTab extends string = string, TCurrentStory = unknown, > = { version: number; savedAt: string; gameState: TGameState; bottomTab: TBottomTab; currentStory: TCurrentStory | null; }; export type SavedGameSnapshotInput< TGameState = unknown, TBottomTab extends string = string, TCurrentStory = unknown, > = Omit< SavedGameSnapshot, 'savedAt' | 'version' > & { savedAt?: string; }; export type RuntimeSaveCheckpointInput = { sessionId: string; bottomTab: TBottomTab; savedAt?: string; }; export type RuntimeSettings = { musicVolume: number; platformTheme: PlatformTheme; }; export type BasicOkResult = { ok: true; }; export type ProfileDashboardCardKey = 'wallet' | 'playTime' | 'playedWorks'; export type ProfileDashboardSummary = { walletBalance: number; totalPlayTimeMs: number; playedWorldCount: number; updatedAt: string | null; dailyFreePoints?: ProfileDailyFreePoints; }; export type ProfileDailyFreePoints = ProfileDailyFreePointsResponse; export type ProfileWalletLedgerEntry = { id: string; amountDelta: number; balanceAfter: number; sourceType: | 'snapshot_sync' | 'new_user_registration_reward' | 'invite_inviter_reward' | 'invite_invitee_reward' | 'points_recharge' | 'membership_period_grant' | 'membership_period_reset' | 'membership_upgrade_grant' | 'daily_free_grant' | 'daily_free_reset' | 'asset_operation_consume' | 'llm_router_consume' | 'asset_operation_refund' | 'recharge_refund_recovery' | 'redeem_code_reward' | 'puzzle_author_incentive_claim' | 'daily_task_reward' | 'game_purchase'; createdAt: string; reason?: string; }; export type ProfileWalletLedgerResponse = { entries: ProfileWalletLedgerEntry[]; }; export type ExternalApiKeyProfile = { keyId: string; name: string; keyPrefix: string; scopes: string[]; createdAt: string; lastUsedAt: string | null; revokedAt: string | null; updatedAt: string; }; export type ExternalApiKeyListResponse = { keys: ExternalApiKeyProfile[]; }; export type ExternalApiKeyCreateResponse = { apiKey: string; key: ExternalApiKeyProfile; }; export type ExternalApiKeyMutationResponse = { key: ExternalApiKeyProfile; }; export type ProfileRechargeProductKind = 'points' | 'membership'; /** 会员状态:来源 Rust `ProfileMembershipStatusToken`,禁止手工维护字面量。 */ export type ProfileMembershipStatus = ProfileMembershipStatusToken; /** 会员档位:`normal` 是非会员占位档位,不可购买。 */ export type ProfileMembershipPlan = ProfileMembershipPlanToken; /** 会员周期:有效期内不支持月年互换,到期后重新选择。 */ export type ProfileMembershipCycleKind = ProfileMembershipCycleKindToken; /** 模型权限:`basic` 仅基础模型,`full` 基础及高性能模型。 */ export type ProfileMembershipModelAccess = ProfileMembershipModelAccessToken; export type ProfileRechargeOrderStatus = | 'pending' | 'paid' | 'failed' | 'closed' | 'refunded' | 'expired'; /** 充点 / 会员商品;`kind` 是前端收窄的联合类型,其余字段以后端生成为准。 */ export type ProfileRechargeProduct = Omit< ProfileRechargeProductResponse, 'kind' > & { kind: ProfileRechargeProductKind; }; /** 会员档位目录行;价格与权益的唯一真相源是后端 `profile_membership_plan` 表。 */ export type ProfileMembershipPlanRecord = ProfileMembershipPlanResponse; export type ProfileMembership = ProfileMembershipResponse; /** 补差升级报价;下单时后端会用同一套规则重算,前端展示的数字不是真相源。 */ export type ProfileMembershipUpgradeQuote = ProfileMembershipUpgradeQuoteResponse; /** 充值订单;`kind` / `status` 是前端收窄的联合类型,其余字段以后端生成为准。 */ export type ProfileRechargeOrder = Omit< ProfileRechargeOrderResponse, 'kind' | 'status' > & { kind: ProfileRechargeProductKind; status: ProfileRechargeOrderStatus; }; /** 充值中心;结构以后端生成为准,仅把商品 / 订单收窄成带联合类型的本地别名。 */ export type ProfileRechargeCenterResponse = Omit< GeneratedProfileRechargeCenterResponse, 'pointProducts' | 'latestOrder' > & { pointProducts: ProfileRechargeProduct[]; latestOrder: ProfileRechargeOrder | null; }; export type WechatMiniProgramPayParams = { appId?: string; timeStamp: string; nonceStr: string; package: string; signType: 'RSA'; paySign: string; }; export type WechatMiniProgramVirtualPayParams = { mode: 'short_series_coin' | 'short_series_goods'; signData: string; paySig: string; signature: string; }; export type WechatH5Payment = { h5Url: string; }; export type WechatNativePayment = { codeUrl: string; expiresAt: string; }; export type CreateProfileRechargeOrderRequest = { productId: string; paymentChannel?: string; }; export type CreateProfileRechargeOrderResponse = { order: ProfileRechargeOrder; center: ProfileRechargeCenterResponse; wechatMiniProgramPayParams?: | WechatMiniProgramPayParams | WechatMiniProgramVirtualPayParams | null; wechatH5Payment?: WechatH5Payment | null; wechatNativePayment?: WechatNativePayment | null; }; export type ConfirmWechatProfileRechargeOrderResponse = { order: ProfileRechargeOrder; center: ProfileRechargeCenterResponse; }; export type WechatProfileRechargeOrderDoneEvent = { orderId: string; status: ProfileRechargeOrderStatus; }; export type WechatProfileRechargeOrderErrorEvent = { message: string; }; export type ProfileFeedbackStatus = 'open'; export type ProfileFeedbackEvidenceItemInput = { fileName: string; contentType: string; sizeBytes: number; dataUrl: string; }; export type SubmitProfileFeedbackRequest = { description: string; contactPhone?: string | null; evidenceItems: ProfileFeedbackEvidenceItemInput[]; }; export type ProfileFeedbackEvidenceItem = { evidenceId: string; fileName: string; contentType: string; sizeBytes: number; }; export type ProfileFeedbackSubmission = { feedbackId: string; status: ProfileFeedbackStatus; createdAt: string; evidenceItems: ProfileFeedbackEvidenceItem[]; }; export type SubmitProfileFeedbackResponse = { feedback: ProfileFeedbackSubmission; }; export type ProfileReferralInviteCenterResponse = { inviteCode: string; inviteLinkPath: string; invitedCount: number; rewardedInviteCount: number; todayInviterRewardCount: number; todayInviterRewardRemaining: number; rewardPoints: number; invitedUsers: ProfileReferralInvitedUser[]; hasRedeemedCode: boolean; boundInviterUserId: string | null; boundAt: string | null; updatedAt: string; }; export type ProfileReferralInvitedUser = { userId: string; displayName: string; avatarUrl: string | null; boundAt: string; }; export type RedeemProfileReferralInviteCodeRequest = { inviteCode: string; }; export type RedeemProfileReferralInviteCodeResponse = { center: ProfileReferralInviteCenterResponse; inviteeRewardGranted: boolean; inviterRewardGranted: boolean; inviteeBalanceAfter: number; inviterBalanceAfter: number; }; export type RedeemProfileRewardCodeRequest = { code: string; }; export type RedeemProfileRewardCodeResponse = { walletBalance: number; amountGranted: number; ledgerEntry: ProfileWalletLedgerEntry; }; export type ProfileTaskCycle = 'daily'; export type TrackingScopeKind = 'site' | 'work' | 'module' | 'user'; export type AnalyticsGranularity = | 'day' | 'week' | 'month' | 'quarter' | 'year'; export type ProfileTaskStatus = | 'incomplete' | 'claimable' | 'claimed' | 'disabled'; export type ProfileTaskItem = { taskId: string; title: string; description: string; eventKey: string; cycle: ProfileTaskCycle; threshold: number; progressCount: number; rewardPoints: number; status: ProfileTaskStatus; dayKey: number; claimedAt: string | null; updatedAt: string; }; export type ProfileTaskCenterResponse = { dayKey: number; walletBalance: number; tasks: ProfileTaskItem[]; updatedAt: string; }; export type ClaimProfileTaskRewardResponse = { taskId: string; dayKey: number; rewardPoints: number; walletBalance: number; ledgerEntry: ProfileWalletLedgerEntry; center: ProfileTaskCenterResponse; }; export type ProfileTaskConfigAdminResponse = { taskId: string; title: string; description: string; eventKey: string; cycle: ProfileTaskCycle; scopeKind: TrackingScopeKind; threshold: number; rewardPoints: number; enabled: boolean; sortOrder: number; createdBy: string; createdAt: string; updatedBy: string; updatedAt: string; }; export type ProfileTaskConfigAdminListResponse = { entries: ProfileTaskConfigAdminResponse[]; }; export type AnalyticsMetricQueryRequest = { eventKey: string; scopeKind: TrackingScopeKind; scopeId: string; granularity: AnalyticsGranularity; }; export type AnalyticsBucketMetric = { bucketKey: string; bucketStartDateKey: number; bucketEndDateKey: number; value: number; }; export type AnalyticsMetricQueryResponse = { buckets: AnalyticsBucketMetric[]; }; export type AdminUpsertProfileTaskConfigRequest = { taskId: string; title: string; description?: string | null; eventKey: string; cycle: ProfileTaskCycle; scopeKind: TrackingScopeKind; threshold: number; rewardPoints: number; enabled?: boolean; sortOrder?: number; }; export type AdminDisableProfileTaskConfigRequest = { taskId: string; }; export type ProfileRedeemCodeMode = 'public' | 'unique' | 'private'; export type ProfileRedeemCodeAdminResponse = { code: string; mode: ProfileRedeemCodeMode; rewardPoints: number; maxUses: number; globalUsedCount: number; enabled: boolean; allowedUserIds: string[]; startsAt?: string | null; expiresAt?: string | null; createdBy: string; createdAt: string; updatedAt: string; }; export type ProfileCodeOperationAdminResponse = { operationId: string; codeKind: 'redeem' | 'invite' | string; code: string; action: 'create' | 'update' | 'disable' | string; operatorUserId: string; createdAt: string; }; export type ProfileRedeemCodeAdminListResponse = { entries: ProfileRedeemCodeAdminResponse[]; operations: ProfileCodeOperationAdminResponse[]; }; export type AdminUpsertProfileRedeemCodeRequest = { code: string; mode: ProfileRedeemCodeMode; rewardPoints: number; maxUses: number; enabled?: boolean; allowedUserIds?: string[]; allowedPublicUserCodes?: string[]; startsAt?: string | null; expiresAt?: string | null; }; export type AdminDisableProfileRedeemCodeRequest = { code: string; }; export type AdminUpsertProfileInviteCodeRequest = { inviteCode: string; metadata?: Record | null; startsAt?: string | null; expiresAt?: string | null; }; export type ProfileInviteCodeAdminResponse = { userId: string; inviteCode: string; metadata: Record; startsAt?: string | null; expiresAt?: string | null; status: 'pending' | 'active' | 'expired'; createdAt: string; updatedAt: string; }; export type ProfileInviteCodeAdminListResponse = { entries: ProfileInviteCodeAdminResponse[]; operations: ProfileCodeOperationAdminResponse[]; }; export type ProfilePlayedWorkSummary = { worldKey: string; ownerUserId: string | null; profileId: string | null; worldType: string | null; worldTitle: string; worldSubtitle: string; firstPlayedAt: string; lastPlayedAt: string; lastObservedPlayTimeMs: number; }; export type ProfilePlayStatsResponse = { totalPlayTimeMs: number; playedWorks: ProfilePlayedWorkSummary[]; updatedAt: string | null; }; export type ProfileSaveArchiveSummary = { worldKey: string; ownerUserId: string | null; profileId: string | null; worldType: string | null; worldName: string; subtitle: string; summaryText: string; coverImageSrc: string | null; lastPlayedAt: string; }; export type ProfileSaveArchiveListResponse = { entries: ProfileSaveArchiveSummary[]; }; export type ProfileSaveArchiveResumeResponse< TGameState = unknown, TBottomTab extends string = string, TCurrentStory = unknown, > = { entry: ProfileSaveArchiveSummary; snapshot: SavedGameSnapshot; }; export type CustomWorldPublicationStatus = 'draft' | 'published'; export type CustomWorldThemeMode = | 'martial' | 'arcane' | 'machina' | 'tide' | 'rift' | 'mythic'; export type CustomWorldProfileRecord = JsonObject & { id?: string; openingCg?: CustomWorldOpeningCgProfile | null; }; export type CustomWorldOpeningCgStatus = | 'not_started' | 'storyboard_generating' | 'video_generating' | 'ready' | 'failed'; export type CustomWorldOpeningCgProfile = { id: string; status: CustomWorldOpeningCgStatus; storyboardImageSrc?: string | null; storyboardAssetId?: string | null; videoSrc?: string | null; videoAssetId?: string | null; posterImageSrc?: string | null; posterAssetId?: string | null; storyboardPrompt?: string | null; videoPrompt?: string | null; imageModel: 'gpt-image-2'; videoModel: string; aspectRatio: '16:9'; imageSize: '2k'; videoResolution: '480p'; durationSeconds: 15; pointCost: 80; estimatedWaitMinutes: 10; generatedAt?: string | null; updatedAt: string; errorMessage?: string | null; }; export type CustomWorldLibraryEntry = { ownerUserId: string; profileId: string; publicWorkCode: string | null; authorPublicUserCode: string | null; profile: TProfile; visibility: CustomWorldPublicationStatus; publishedAt: string | null; updatedAt: string; authorDisplayName: string; worldName: string; subtitle: string; summaryText: string; coverImageSrc: string | null; themeMode: CustomWorldThemeMode; playableNpcCount: number; landmarkCount: number; playCount?: number; remixCount?: number; likeCount?: number; recentPlayCount7d?: number; }; export type CustomWorldGalleryCard = Omit< CustomWorldLibraryEntry, 'profile' >; export type CustomWorldLibraryResponse = { entries: CustomWorldLibraryEntry[]; }; export type CustomWorldLibraryMutationResponse< TProfile = CustomWorldProfileRecord, > = { entry: CustomWorldLibraryEntry; entries: CustomWorldLibraryEntry[]; }; export type CustomWorldGalleryResponse = { entries: CustomWorldGalleryCard[]; }; export type CustomWorldGalleryDetailResponse< TProfile = CustomWorldProfileRecord, > = { entry: CustomWorldLibraryEntry; }; export type PlatformBrowseHistoryEntry = { ownerUserId: string; profileId: string; worldName: string; subtitle: string; summaryText: string; coverImageSrc: string | null; themeMode: CustomWorldThemeMode; authorDisplayName: string; visitedAt: string; }; export type PlatformBrowseHistoryWriteEntry = Omit< PlatformBrowseHistoryEntry, 'visitedAt' > & { visitedAt?: string; }; export type PlatformBrowseHistoryResponse = { entries: PlatformBrowseHistoryEntry[]; }; export type PlatformBrowseHistoryBatchSyncRequest = { entries: PlatformBrowseHistoryWriteEntry[]; }; export const CUSTOM_WORLD_GENERATION_MODES = ['fast', 'full'] as const; export type CustomWorldGenerationMode = (typeof CUSTOM_WORLD_GENERATION_MODES)[number]; export const CUSTOM_WORLD_SESSION_STATUSES = [ 'clarifying', 'ready_to_generate', 'generating', 'completed', 'generation_error', ] as const; export type CustomWorldSessionStatus = (typeof CUSTOM_WORLD_SESSION_STATUSES)[number]; export type CustomWorldQuestion = { id: string; label: string; question: string; answer?: string; }; export type CustomWorldGenerationStep = { id: string; label: string; detail: string; completed: number; total: number; status: 'pending' | 'active' | 'completed'; }; export type CustomWorldGenerationProgress = { phaseId: string; phaseLabel: string; phaseDetail: string; batchLabel?: string; overallProgress: number; completedWeight: number; totalWeight: number; elapsedMs: number; estimatedRemainingMs: number | null; activeStepIndex: number; steps: CustomWorldGenerationStep[]; }; export type GenerateCustomWorldProfileOptions = { onProgress?: (progress: CustomWorldGenerationProgress) => void; signal?: AbortSignal; }; export type GenerateCustomWorldProfileInput = { settingText: string; creatorIntent?: JsonObject | null; generationMode?: CustomWorldGenerationMode; }; export type CreateCustomWorldSessionRequest = { settingText: string; creatorIntent?: JsonObject | null; generationMode: CustomWorldGenerationMode; }; export type AnswerCustomWorldSessionQuestionRequest = { questionId: string; answer: string; }; export type CustomWorldSessionSummary = { sessionId: string; status: CustomWorldSessionStatus; questions: CustomWorldQuestion[]; createdAt: string; updatedAt: string; }; export type CustomWorldSessionRecord = CustomWorldSessionSummary & { settingText: string; creatorIntent?: JsonObject | null; generationMode: CustomWorldGenerationMode; result?: JsonObject; lastError?: string; };