Merge branch 'master' into codex/puzzle-clear-template-runtime-fixes

# Conflicts:
#	.hermes/shared-memory/decision-log.md
#	.hermes/shared-memory/project-overview.md
#	docs/【开发运维】本地开发验证与生产运维-2026-05-15.md
#	scripts/dev.test.ts
#	server-rs/crates/api-server/src/creation_entry_config.rs
#	server-rs/crates/api-server/src/wooden_fish.rs
#	server-rs/crates/module-auth/src/lib.rs
#	server-rs/crates/spacetime-client/src/wooden_fish.rs
#	server-rs/crates/spacetime-module/src/auth/procedures.rs
#	src/components/custom-world-home/creationWorkShelf.ts
#	src/components/platform-entry/PlatformEntryFlowShellImpl.tsx
#	src/components/rpg-entry/rpgEntryWorldPresentation.ts
#	src/services/miniGameDraftGenerationProgress.test.ts
#	src/services/miniGameDraftGenerationProgress.ts
This commit is contained in:
2026-06-04 11:24:14 +08:00
451 changed files with 18452 additions and 5266 deletions

View File

@@ -147,26 +147,34 @@ pub async fn execute_wooden_fish_action(
wooden_fish_json(payload, &request_context, WOODEN_FISH_CREATION_PROVIDER)?;
let owner_user_id = authenticated.claims().user_id().to_string();
let author_display_name = resolve_author_display_name(&state, &authenticated);
maybe_generate_hit_object_asset(
let result = execute_wooden_fish_action_with_generated_assets(
&state,
&request_context,
&session_id,
owner_user_id.as_str(),
&owner_user_id,
&author_display_name,
&mut payload,
)
.await?;
maybe_generate_hit_sound_asset(&mut payload);
let response = state
.spacetime_client()
.execute_wooden_fish_action(session_id, owner_user_id, author_display_name, payload)
.await
.map_err(|error| {
wooden_fish_error_response(
&request_context,
WOODEN_FISH_CREATION_PROVIDER,
map_wooden_fish_client_error(error),
)
})?;
.await;
if result
.as_ref()
.err()
.is_some_and(|response| response.status().is_server_error())
&& matches!(
payload.action_type,
shared_contracts::wooden_fish::WoodenFishActionType::CompileDraft
)
{
mark_wooden_fish_generation_failed(
&state,
&request_context,
&session_id,
owner_user_id.as_str(),
author_display_name.as_str(),
)
.await;
}
let response = result?;
Ok(json_success_body(Some(&request_context), response))
}
@@ -372,16 +380,24 @@ async fn build_wooden_fish_draft(
payload: &WoodenFishWorkspaceCreateRequest,
state: &AppState,
) -> Result<WoodenFishDraftResponse, Response> {
Ok(WoodenFishDraftResponse {
let work_title = resolve_wooden_fish_work_title(
state,
&payload.work_description,
&payload.hit_object_prompt,
)
.await?;
Ok(build_wooden_fish_draft_response(payload, work_title))
}
fn build_wooden_fish_draft_response(
payload: &WoodenFishWorkspaceCreateRequest,
work_title: String,
) -> WoodenFishDraftResponse {
WoodenFishDraftResponse {
template_id: WOODEN_FISH_TEMPLATE_ID.to_string(),
template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(),
profile_id: None,
work_title: resolve_wooden_fish_work_title(
state,
&payload.work_description,
&payload.hit_object_prompt,
)
.await?,
work_title,
work_description: payload.work_description.trim().to_string(),
theme_tags: normalize_tags(payload.theme_tags.clone()),
hit_object_prompt: clean_string(&payload.hit_object_prompt, DEFAULT_HIT_OBJECT_PROMPT),
@@ -401,7 +417,7 @@ async fn build_wooden_fish_draft(
.or_else(|| Some(default_wooden_fish_hit_sound_asset())),
cover_image_src: None,
generation_status: WoodenFishGenerationStatus::Draft,
})
}
}
fn validate_workspace_request(
@@ -543,6 +559,62 @@ async fn maybe_generate_hit_object_asset(
Ok(())
}
async fn execute_wooden_fish_action_with_generated_assets(
state: &AppState,
request_context: &RequestContext,
session_id: &str,
owner_user_id: &str,
author_display_name: &str,
payload: &mut WoodenFishActionRequest,
) -> Result<shared_contracts::wooden_fish::WoodenFishActionResponse, Response> {
maybe_generate_hit_object_asset(state, request_context, session_id, owner_user_id, payload)
.await?;
maybe_generate_hit_sound_asset(payload);
state
.spacetime_client()
.execute_wooden_fish_action(
session_id.to_string(),
owner_user_id.to_string(),
author_display_name.to_string(),
payload.clone(),
)
.await
.map_err(|error| {
wooden_fish_error_response(
request_context,
WOODEN_FISH_CREATION_PROVIDER,
map_wooden_fish_client_error(error),
)
})
}
async fn mark_wooden_fish_generation_failed(
state: &AppState,
request_context: &RequestContext,
session_id: &str,
owner_user_id: &str,
author_display_name: &str,
) {
if let Err(error) = state
.spacetime_client()
.mark_wooden_fish_generation_failed(
session_id.to_string(),
owner_user_id.to_string(),
author_display_name.to_string(),
)
.await
{
tracing::error!(
provider = WOODEN_FISH_CREATION_PROVIDER,
session_id,
owner_user_id,
request_id = request_context.request_id(),
error = %error,
"敲木鱼草稿生成失败后的状态回写失败"
);
}
}
fn default_wooden_fish_hit_object_asset() -> WoodenFishImageAsset {
WoodenFishImageAsset {
asset_id: DEFAULT_HIT_OBJECT_ASSET_ID.to_string(),