import type { ExternalGenerationJobStatusRecord, ExternalGenerationQueueOverview, ExternalGenerationTaskRecord, } from '../../../packages/shared/src/contracts/externalGeneration'; export type ExternalGenerationQueueStatus = { currentStatus?: 'queued' | 'running' | 'completed' | 'failed' | null; currentProgress?: number | null; pendingCount?: number | null; runningCount?: number | null; tasks?: ExternalGenerationTaskRecord[] | null; unacknowledgedTerminalCount?: number | null; }; export type ExternalGenerationQueueTaskPresentation = { id: string; title: string; statusLabel: string; priceLabel: string; detail: string; tone: 'profile' | 'danger' | 'success'; }; export type ExternalGenerationQueuePresentation = { statusLabel: string | null; progressLabel: string | null; pendingLabel: string; runningLabel: string; pendingCount: number; runningCount: number; unacknowledgedTerminalCount: number; progress: number | null; tasks: ExternalGenerationQueueTaskPresentation[]; shouldShow: boolean; }; export function buildExternalGenerationQueueStatus( overview: ExternalGenerationQueueOverview | null, job: ExternalGenerationJobStatusRecord | null, tasks: ExternalGenerationTaskRecord[] | null = null, ): ExternalGenerationQueueStatus | null { if (!overview && !job && !tasks?.length) { return null; } return { currentStatus: job?.status ?? null, currentProgress: job?.progress ?? null, pendingCount: overview?.pendingCount ?? null, runningCount: overview?.runningCount ?? null, unacknowledgedTerminalCount: overview?.unacknowledgedTerminalCount ?? null, tasks, }; } function isActiveExternalGenerationStatus( status: ExternalGenerationQueueStatus['currentStatus'], ) { return status === 'queued' || status === 'running'; } function isUnacknowledgedExternalGenerationTerminalTask( task: ExternalGenerationTaskRecord, ) { return ( (task.status === 'completed' || task.status === 'failed') && !task.notificationAcknowledgedAt ); } export function shouldUseFastExternalGenerationTaskPolling( status: ExternalGenerationQueueStatus | null | undefined, ) { const pendingCount = normalizeExternalGenerationQueueCount( status?.pendingCount, ); const runningCount = normalizeExternalGenerationQueueCount( status?.runningCount, ); const unacknowledgedTerminalCount = normalizeExternalGenerationQueueCount( status?.unacknowledgedTerminalCount, ); return Boolean( isActiveExternalGenerationStatus(status?.currentStatus ?? null) || pendingCount > 0 || runningCount > 0 || unacknowledgedTerminalCount > 0 || (status?.tasks ?? []).some( (task) => task.status === 'queued' || task.status === 'running' || isUnacknowledgedExternalGenerationTerminalTask(task), ), ); } export function resolveExternalGenerationQueueStatusLabel( status: ExternalGenerationQueueStatus['currentStatus'], ) { if (status === 'queued') { return '排队中'; } if (status === 'running') { return '生成中'; } if (status === 'failed') { return '生成失败'; } if (status === 'completed') { return '已完成'; } return null; } function resolveExternalGenerationQueueOverviewLabel( pendingCount: number, runningCount: number, ) { if (runningCount > 0) { return '生成中'; } if (pendingCount > 0) { return '排队中'; } return null; } export function normalizeExternalGenerationQueueCount( value: number | null | undefined, ) { if (typeof value !== 'number' || !Number.isFinite(value)) { return 0; } return Math.max(0, Math.round(value)); } export function normalizeExternalGenerationQueueProgress( value: number | null | undefined, ) { if (typeof value !== 'number' || !Number.isFinite(value)) { return null; } return Math.max(0, Math.min(100, Math.round(value))); } export function buildExternalGenerationTaskPresentation( task: ExternalGenerationTaskRecord, ): ExternalGenerationQueueTaskPresentation { const statusLabel = resolveExternalGenerationQueueStatusLabel(task.status) ?? '待处理'; return { id: task.jobId, title: task.requestLabel.trim() || task.jobKind, statusLabel, priceLabel: task.priceMudPoints > 0 ? `${task.priceMudPoints}泥点` : '未计费', detail: task.error?.trim() || task.phaseDetail || task.updatedAt, tone: task.status === 'failed' ? 'danger' : task.status === 'completed' ? 'success' : 'profile', }; } export function buildExternalGenerationQueuePresentation( status: ExternalGenerationQueueStatus | null | undefined, ): ExternalGenerationQueuePresentation { const pendingCount = normalizeExternalGenerationQueueCount( status?.pendingCount, ); const runningCount = normalizeExternalGenerationQueueCount( status?.runningCount, ); const unacknowledgedTerminalCount = normalizeExternalGenerationQueueCount( status?.unacknowledgedTerminalCount, ); const progress = normalizeExternalGenerationQueueProgress( status?.currentProgress, ); const isCompletedCurrentJob = status?.currentStatus === 'completed'; const currentStatusLabel = resolveExternalGenerationQueueStatusLabel( status?.currentStatus ?? null, ); const overviewStatusLabel = resolveExternalGenerationQueueOverviewLabel( pendingCount, runningCount, ); const statusLabel = isCompletedCurrentJob ? overviewStatusLabel : (currentStatusLabel ?? overviewStatusLabel); const progressValue = isCompletedCurrentJob ? null : progress; return { statusLabel, progressLabel: progressValue == null ? null : `${progressValue}%`, pendingLabel: pendingCount.toString(), runningLabel: runningCount.toString(), pendingCount, runningCount, unacknowledgedTerminalCount, progress: progressValue, tasks: (status?.tasks ?? []) .slice(0, 5) .map(buildExternalGenerationTaskPresentation), shouldShow: Boolean( statusLabel || pendingCount > 0 || runningCount > 0 || unacknowledgedTerminalCount > 0 || (status?.tasks?.length ?? 0) > 0, ), }; }