feat: unify phase one creation flow

This commit is contained in:
2026-05-30 05:05:02 +08:00
parent 3a87b2d966
commit 26975644b5
33 changed files with 2037 additions and 539 deletions

View File

@@ -163,7 +163,14 @@ pub(super) async fn compile_match3d_draft_for_session(
.clone()
.unwrap_or_else(|| fallback_work_metadata.tags.clone());
let billing_asset_id = format!("{}:{}:{}", session_id, profile_id, current_utc_micros());
execute_billable_match3d_draft_generation(
let compile_session_id = session_id.clone();
let compile_owner_user_id = owner_user_id.clone();
let compile_profile_id = profile_id.clone();
let compile_initial_game_name = initial_game_name.clone();
let compile_requested_summary = requested_summary.clone();
let compile_initial_tags = initial_tags.clone();
let compile_requested_cover_image_src = requested_cover_image_src.clone();
let result = execute_billable_match3d_draft_generation(
state,
request_context,
owner_user_id.as_str(),
@@ -307,7 +314,108 @@ pub(super) async fn compile_match3d_draft_for_session(
Ok((next_session, generated_item_assets))
},
)
.await;
if let Err(response) = result.as_ref()
&& response.status().is_server_error()
{
let failure_message = match3d_response_failure_message(response);
persist_failed_match3d_draft_generation(
state,
request_context,
authenticated,
compile_session_id,
compile_owner_user_id,
compile_profile_id,
compile_initial_game_name,
compile_requested_summary,
compile_initial_tags,
compile_requested_cover_image_src,
failure_message,
)
.await;
}
result
}
#[allow(clippy::too_many_arguments)]
async fn persist_failed_match3d_draft_generation(
state: &AppState,
request_context: &RequestContext,
authenticated: &AuthenticatedAccessToken,
session_id: String,
owner_user_id: String,
profile_id: String,
game_name: String,
summary: Option<String>,
tags: Vec<String>,
cover_image_src: Option<String>,
failure_message: String,
) {
let failure_assets_json = serialize_match3d_failed_generation_assets(failure_message.as_str());
if let Err(persist_error) = upsert_match3d_draft_snapshot(
state,
request_context,
authenticated,
session_id,
owner_user_id,
profile_id,
Some(game_name),
summary.or_else(|| Some(String::new())),
Some(serde_json::to_string(&tags).unwrap_or_default()),
cover_image_src,
None,
failure_assets_json,
)
.await
{
tracing::error!(
provider = MATCH3D_AGENT_PROVIDER,
status = ?persist_error.status(),
"抓大鹅草稿生成失败后的状态回写失败"
);
}
}
fn serialize_match3d_failed_generation_assets(message: &str) -> Option<String> {
let background_asset = Match3DGeneratedBackgroundAsset {
prompt: String::new(),
status: "failed".to_string(),
error: Some(message.trim().to_string()),
..Default::default()
};
let assets = vec![Match3DGeneratedItemAssetJson {
item_id: "match3d-generation-failure".to_string(),
item_name: "生成失败".to_string(),
item_size: Some(MATCH3D_ITEM_SIZE_LARGE.to_string()),
image_src: None,
image_object_key: None,
image_views: Vec::new(),
model_src: None,
model_object_key: None,
model_file_name: None,
task_uuid: None,
subscription_key: None,
sound_prompt: None,
background_music_title: None,
background_music_style: None,
background_music_prompt: None,
background_music: None,
click_sound: None,
background_asset: Some(background_asset),
status: "failed".to_string(),
error: Some(message.trim().to_string()),
}];
serde_json::to_string(&assets).ok()
}
fn match3d_response_failure_message(response: &Response) -> String {
response
.extensions()
.get::<String>()
.cloned()
.unwrap_or_else(|| format!("抓大鹅草稿生成失败HTTP {}", response.status()))
}
/// 中文注释:抓大鹅草稿生成是一次完整外部生成动作,按 session/profile 幂等预扣 10 泥点。