fix: refresh custom world publish gate diagnostics
This commit is contained in:
@@ -38,6 +38,7 @@ use spacetime_client::{
|
||||
CustomWorldWorkSummaryRecord, SpacetimeClientError,
|
||||
};
|
||||
use std::convert::Infallible;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
api_response::json_success_body,
|
||||
@@ -471,6 +472,7 @@ pub async fn get_custom_world_agent_session(
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
log_custom_world_publish_gate_diagnostics("get_session", &session);
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
@@ -998,6 +1000,19 @@ pub async fn execute_custom_world_agent_action(
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
|
||||
if matches!(
|
||||
action.as_str(),
|
||||
"sync_result_profile" | "publish_world" | "draft_foundation"
|
||||
) {
|
||||
if let Ok(session) = state
|
||||
.spacetime_client()
|
||||
.get_custom_world_agent_session(session_id.clone(), owner_user_id.clone())
|
||||
.await
|
||||
{
|
||||
log_custom_world_publish_gate_diagnostics(action.as_str(), &session);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
json!({
|
||||
@@ -1131,6 +1146,109 @@ fn map_custom_world_agent_session_response(
|
||||
}
|
||||
}
|
||||
|
||||
fn log_custom_world_publish_gate_diagnostics(
|
||||
source: &str,
|
||||
session: &CustomWorldAgentSessionRecord,
|
||||
) {
|
||||
let draft_profile = session.draft_profile.as_object();
|
||||
let preview_profile = session
|
||||
.result_preview
|
||||
.as_ref()
|
||||
.and_then(|preview| preview.get("preview"))
|
||||
.and_then(Value::as_object);
|
||||
let profile = preview_profile.or(draft_profile);
|
||||
let blocker_codes = session
|
||||
.publish_gate
|
||||
.as_ref()
|
||||
.map(|gate| {
|
||||
gate.blockers
|
||||
.iter()
|
||||
.map(|blocker| blocker.code.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
info!(
|
||||
target: "custom_world.publish_gate",
|
||||
source,
|
||||
session_id = %session.session_id,
|
||||
stage = %session.stage,
|
||||
publish_ready = session.publish_gate.as_ref().map(|gate| gate.publish_ready).unwrap_or(false),
|
||||
blocker_count = session.publish_gate.as_ref().map(|gate| gate.blocker_count).unwrap_or(0),
|
||||
blocker_codes = %blocker_codes,
|
||||
has_draft_profile = session.draft_profile.as_object().map(|value| !value.is_empty()).unwrap_or(false),
|
||||
has_result_preview = session.result_preview.is_some(),
|
||||
preview_source = session.result_preview.as_ref().and_then(|value| value.get("source")).and_then(Value::as_str).unwrap_or(""),
|
||||
has_world_hook = has_custom_world_publish_text(profile, &["worldHook", "creatorIntent.worldHook", "anchorContent.worldPromise.hook", "settingText"]),
|
||||
has_player_premise = has_custom_world_publish_text(profile, &["playerPremise", "creatorIntent.playerPremise", "anchorContent.playerEntryPoint.openingIdentity", "anchorContent.playerEntryPoint.openingProblem", "anchorContent.playerEntryPoint.entryMotivation"]),
|
||||
has_core_conflicts = has_custom_world_non_empty_text_array(profile, "coreConflicts"),
|
||||
has_main_chapter = has_custom_world_array(profile, "chapters") || has_custom_world_array(profile, "sceneChapterBlueprints") || has_custom_world_array(profile, "sceneChapters"),
|
||||
has_scene_act = has_custom_world_scene_act(profile),
|
||||
"custom world publish gate diagnostics"
|
||||
);
|
||||
}
|
||||
|
||||
fn has_custom_world_publish_text(profile: Option<&Map<String, Value>>, paths: &[&str]) -> bool {
|
||||
paths.iter().any(|path| {
|
||||
let mut segments = path.split('.');
|
||||
let Some(first_segment) = segments.next() else {
|
||||
return false;
|
||||
};
|
||||
let mut current = profile.and_then(|value| value.get(first_segment));
|
||||
for segment in segments {
|
||||
current = current.and_then(|value| value.get(segment));
|
||||
}
|
||||
current
|
||||
.and_then(Value::as_str)
|
||||
.map(str::trim)
|
||||
.map(|value| !value.is_empty())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
||||
fn has_custom_world_non_empty_text_array(profile: Option<&Map<String, Value>>, key: &str) -> bool {
|
||||
profile
|
||||
.and_then(|value| value.get(key))
|
||||
.and_then(Value::as_array)
|
||||
.map(|items| {
|
||||
items.iter().any(|item| {
|
||||
item.as_str()
|
||||
.map(str::trim)
|
||||
.is_some_and(|value| !value.is_empty())
|
||||
})
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn has_custom_world_array(profile: Option<&Map<String, Value>>, key: &str) -> bool {
|
||||
profile
|
||||
.and_then(|value| value.get(key))
|
||||
.and_then(Value::as_array)
|
||||
.map(|items| !items.is_empty())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn has_custom_world_scene_act(profile: Option<&Map<String, Value>>) -> bool {
|
||||
profile
|
||||
.and_then(|value| {
|
||||
value
|
||||
.get("sceneChapterBlueprints")
|
||||
.or_else(|| value.get("sceneChapters"))
|
||||
})
|
||||
.and_then(Value::as_array)
|
||||
.map(|chapters| {
|
||||
chapters.iter().any(|chapter| {
|
||||
chapter
|
||||
.get("acts")
|
||||
.and_then(Value::as_array)
|
||||
.map(|acts| !acts.is_empty())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn map_custom_world_publish_gate_response(
|
||||
gate: CustomWorldPublishGateRecord,
|
||||
) -> CustomWorldPublishGateResponse {
|
||||
|
||||
Reference in New Issue
Block a user