音效失败对外只返回稳定文案

把音效任务加入用户可见失败文案白名单,不再透出 ElevenLabs 端点与传输层诊断。

新增音效失败文案脱敏测试,原始诊断仍保留在任务记录、tracing 与审计事件中。
This commit is contained in:
2026-08-07 08:12:03 +00:00
parent 92085dfdd5
commit 7733202bb3
@@ -21,6 +21,7 @@ use spacetime_client::{
use crate::editor_generation_queue::{
EDITOR_BACKGROUND_REMOVAL_JOB_KIND, EDITOR_CHARACTER_ANIMATION_GENERATION_JOB_KIND,
EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND,
};
use crate::{
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
@@ -202,9 +203,9 @@ fn map_external_generation_job_status(
}
}
/// 外部任务表保存的失败文本同时服务于 worker 诊断和用户通知。抠图角色动作透明化任务的
/// 原始失败文本可能包含内部 provider、分割模型或实现细节,因此只能在普通用户读取边界
/// 替换成稳定文案。
/// 外部任务表保存的失败文本同时服务于 worker 诊断和用户通知。抠图角色动作透明化和音效
/// 任务的原始失败文本可能包含内部 provider、分割模型、请求端点或 HTTP 传输层细节,因此
/// 只能在普通用户读取边界替换成稳定文案。
/// 原始值仍留在任务记录、tracing 和后台审计路径中。
fn user_visible_external_generation_error(job_kind: &str, error: Option<String>) -> Option<String> {
if job_kind == EDITOR_BACKGROUND_REMOVAL_JOB_KIND && error.is_some() {
@@ -213,6 +214,10 @@ fn user_visible_external_generation_error(job_kind: &str, error: Option<String>)
if job_kind == EDITOR_CHARACTER_ANIMATION_GENERATION_JOB_KIND && error.is_some() {
return Some("角色动作生成失败,请稍后重试。".to_string());
}
// 音效失败文本来自 ElevenLabs / reqwest,会带上请求端点、底层错误链和上游状态码。
if job_kind == EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND && error.is_some() {
return Some("音效生成失败,请稍后重试。".to_string());
}
error
}
@@ -470,6 +475,50 @@ mod tests {
assert!(!lower.contains("provider"));
}
#[test]
fn sound_effect_failure_hides_provider_and_transport_details_from_owner() {
let job = ExternalGenerationJobSummaryRecord {
job_id: "task-sound-effect-failed".to_string(),
job_kind: EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND.to_string(),
owner_user_id: "user-1".to_string(),
source_module: "editor-canvas".to_string(),
source_entity_id: "project-1".to_string(),
request_label: "音效生成".to_string(),
request_prompt: None,
status: "failed".to_string(),
last_error_message: Some(
"请求 ElevenLabs 音效生成失败:error sending request for url \
(https://api.elevenlabs.io/v1/sound-generation?output_format=mp3_44100_128): \
connection error: Connection refused (os error 111)"
.to_string(),
),
created_at: "2026-08-07T08:00:00Z".to_string(),
started_at: Some("2026-08-07T08:00:01Z".to_string()),
completed_at: Some("2026-08-07T08:00:10Z".to_string()),
updated_at: "2026-08-07T08:00:10Z".to_string(),
updated_at_micros: 1_000,
price_mud_points: 5,
refund_ledger_id: None,
notification_acknowledged_at: None,
notification_acknowledged_at_micros: None,
phase: None,
warning_message: None,
};
let status = map_external_generation_job_status(job.clone());
let task = map_external_generation_task_record(job);
assert_eq!(status.error.as_deref(), Some("音效生成失败,请稍后重试。"));
assert_eq!(task.error.as_deref(), Some("音效生成失败,请稍后重试。"));
for value in [status.error, task.error].into_iter().flatten() {
let lower = value.to_ascii_lowercase();
assert!(!lower.contains("elevenlabs"));
assert!(!lower.contains("api.elevenlabs.io"));
assert!(!lower.contains("sound-generation"));
assert!(!lower.contains("os error"));
}
}
#[test]
fn unrelated_generation_failure_keeps_its_user_visible_message() {
let message = user_visible_external_generation_error(