Files
yingqing/core/frontend/src/generation-error.ts
T

104 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* AI 生成失败的普通用户展示层。
*
* 页面只消费这里的稳定 code,不解析供应商名称、HTTP 状态、URL 或英文异常。
* 本文件不发请求、不依赖 React,后续脚本/图片/视频页面可按需接入。
*/
export type GenerationOperation =
| "script_generate"
| "image_generate"
| "base_asset_generate"
| "triview_generate"
| "storyboard_generate"
| "video_generate"
| "voiceover_generate"
| "entity_extract";
export type GenerationErrorCode =
| "provider_quota_exhausted"
| "provider_rate_limited"
| "provider_unavailable"
| "provider_config_error"
| "model_unavailable"
| "content_rejected"
| "invalid_input"
| "asset_unavailable"
| "user_credit_insufficient"
| "task_timeout"
| "processing_failed"
| "unknown";
export type GenerationErrorAction = "retry" | "retry_later" | "revise_input" | "recharge" | "contact_support" | "none";
export type PublicGenerationError = {
domain: "generation";
code: GenerationErrorCode;
operation: GenerationOperation;
action: GenerationErrorAction;
retryable: boolean;
reference_id?: string;
};
export type GenerationErrorPresentation = {
title: string;
description: string;
action: GenerationErrorAction;
retryable: boolean;
referenceId?: string;
};
const OPERATION_LABEL: Record<GenerationOperation, string> = {
script_generate: "脚本",
image_generate: "图片",
base_asset_generate: "基础素材",
triview_generate: "三视图",
storyboard_generate: "故事板",
video_generate: "视频",
voiceover_generate: "配音",
entity_extract: "脚本信息"
};
type Copy = (operation: string) => Pick<GenerationErrorPresentation, "title" | "description">;
const ERROR_COPY: Record<GenerationErrorCode, Copy> = {
provider_quota_exhausted: (operation) => ({ title: `${operation}暂时不可用`, description: "生成服务正在处理中,请稍后再试。" }),
provider_rate_limited: (operation) => ({ title: `${operation}请求较多`, description: "当前生成请求较多,请稍后再试。" }),
provider_unavailable: (operation) => ({ title: `${operation}暂时不可用`, description: "生成服务暂时不可用,请稍后重试。" }),
provider_config_error: (operation) => ({ title: `${operation}暂时不可用`, description: "平台正在处理该问题,请稍后再试。" }),
model_unavailable: (operation) => ({ title: `${operation}暂时不可用`, description: "当前生成能力暂不可用,请稍后再试。" }),
content_rejected: (operation) => ({ title: `${operation}内容需要调整`, description: "内容未通过生成审核,请调整描述或素材后重试。" }),
invalid_input: (operation) => ({ title: `${operation}内容需检查`, description: "请检查描述、参数或素材格式后重试。" }),
asset_unavailable: () => ({ title: "引用素材当前不可用", description: "请重新上传或更换素材后重试。" }),
user_credit_insufficient: () => ({ title: "可用积分不足", description: "充值后可继续生成。" }),
task_timeout: (operation) => ({ title: `${operation}生成时间过长`, description: "服务响应较慢,未完成生成,请重试。" }),
processing_failed: (operation) => ({ title: `${operation}结果处理失败`, description: "本次未生成可用结果,请重试。" }),
unknown: (operation) => ({ title: `${operation}遇到问题`, description: "请稍后重试;若多次出现,请提供任务编号以便排查。" })
};
export function isPublicGenerationError(value: unknown): value is PublicGenerationError {
if (!value || typeof value !== "object") return false;
const candidate = value as Partial<PublicGenerationError>;
return candidate.domain === "generation"
&& typeof candidate.code === "string" && Object.hasOwn(ERROR_COPY, candidate.code)
&& typeof candidate.operation === "string" && Object.hasOwn(OPERATION_LABEL, candidate.operation)
&& typeof candidate.action === "string"
&& typeof candidate.retryable === "boolean";
}
export function presentGenerationError(error: PublicGenerationError): GenerationErrorPresentation {
const copy = ERROR_COPY[error.code] ?? ERROR_COPY.unknown;
return {
...copy(OPERATION_LABEL[error.operation] ?? "生成"),
action: error.action,
retryable: error.retryable,
referenceId: error.reference_id
};
}
export function generationErrorText(error: unknown, fallback: string): string {
if (!isPublicGenerationError(error)) return fallback;
const presentation = presentGenerationError(error);
return `${presentation.title}${presentation.description}`;
}