import type { CustomWorldAgentMessage, CustomWorldAgentOperationRecord, CustomWorldWorkSummary, } from '../../../packages/shared/src/contracts/customWorldAgent'; import type { CustomWorldLibraryEntry } from '../../../packages/shared/src/contracts/runtime'; import { ApiClientError, isTimeoutError } from '../../services/apiClient'; import type { CustomWorldProfile } from '../../types'; export function resolveRpgEntryErrorMessage(error: unknown, fallback: string) { if (isTimeoutError(error)) { if (/智能创作/u.test(fallback)) { return '开启智能创作工作区超时,请确认运行时后端已启动后重试。'; } if (/拼图/u.test(fallback)) { return '开启拼图创作工作台超时,请确认运行时后端已启动后重试。'; } if (/大鱼吃小鱼/u.test(fallback)) { return '开启大鱼吃小鱼创作工作台超时,请确认运行时后端已启动后重试。'; } if (/共创工作台/u.test(fallback)) { return '开启创作工作台超时,请确认运行时后端已启动后重试。'; } return '请求超时,请稍后重试。'; } if ( error instanceof ApiClientError && error.status === 401 && (error.code === 'UNAUTHORIZED' || error.message.includes('Authorization Bearer Token')) ) { return '当前登录状态已失效,请重新登录后继续。'; } return error instanceof Error ? error.message : fallback; } export function createFailedRpgEntryAgentOperation(params: { type: CustomWorldAgentOperationRecord['type']; phaseLabel: string; error: string; }): CustomWorldAgentOperationRecord { return { operationId: `local-failed-${Date.now()}`, type: params.type, status: 'failed', phaseLabel: params.phaseLabel, phaseDetail: params.error, progress: 0, error: params.error, startedAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; } export function buildOptimisticRpgEntryAgentMessage( payload: Pick, ): CustomWorldAgentMessage { return { ...payload, createdAt: new Date().toISOString(), relatedOperationId: null, }; } export function normalizeRpgEntryAgentBackedProfile( profile: CustomWorldProfile, ) { // 中文注释:保存前 canonicalize 已迁到 server-rs; // 这里保留透传函数只为了兼容旧导入,不再改写正式 profile 字段。 return profile; } export function stringifyRpgEntryAgentBackedProfile( profile: CustomWorldProfile, ) { return JSON.stringify(profile); } export function buildRpgEntryCreationHubFallbackItems( entries: CustomWorldLibraryEntry[], ): CustomWorldWorkSummary[] { return entries .filter((entry) => entry.visibility === 'published') .map((entry) => ({ workId: `fallback:${entry.profileId}`, sourceType: 'published_profile', status: 'published', title: entry.worldName, subtitle: entry.subtitle || '已发布作品', summary: entry.summaryText || '继续补完这个世界的设定与游玩入口。', coverImageSrc: entry.coverImageSrc, coverRenderMode: 'image', coverCharacterImageSrcs: [], updatedAt: entry.updatedAt, publishedAt: entry.publishedAt, stage: null, stageLabel: '已发布', playableNpcCount: entry.playableNpcCount, landmarkCount: entry.landmarkCount, roleVisualReadyCount: 0, roleAnimationReadyCount: 0, roleAssetSummaryLabel: null, sessionId: null, profileId: entry.profileId, canResume: false, canEnterWorld: true, })); } /** * 兼容创作链工作包已经接入的旧 helper 命名,避免本轮迁移波及其他并行改动。 */ export const resolveRpgCreationErrorMessage = resolveRpgEntryErrorMessage; export const createFailedAgentOperation = createFailedRpgEntryAgentOperation; export const buildOptimisticAgentMessage = buildOptimisticRpgEntryAgentMessage; export const normalizeAgentBackedProfile = normalizeRpgEntryAgentBackedProfile; export const stringifyAgentBackedProfile = stringifyRpgEntryAgentBackedProfile; export const buildCreationHubFallbackItems = buildRpgEntryCreationHubFallbackItems;