refactor: split large modules and normalize rust layout
This commit is contained in:
957
server-rs/crates/spacetime-client/src/mapper/custom_world.rs
Normal file
957
server-rs/crates/spacetime-client/src/mapper/custom_world.rs
Normal file
@@ -0,0 +1,957 @@
|
||||
use super::*;
|
||||
|
||||
impl From<CustomWorldProfileUpsertRecordInput> for CustomWorldProfileUpsertInput {
|
||||
fn from(input: CustomWorldProfileUpsertRecordInput) -> Self {
|
||||
Self {
|
||||
profile_id: input.profile_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
public_work_code: input.public_work_code,
|
||||
author_public_user_code: input.author_public_user_code,
|
||||
source_agent_session_id: input.source_agent_session_id,
|
||||
world_name: input.world_name,
|
||||
subtitle: input.subtitle,
|
||||
summary_text: input.summary_text,
|
||||
theme_mode: map_custom_world_theme_mode(input.theme_mode),
|
||||
cover_image_src: input.cover_image_src,
|
||||
profile_payload_json: input.profile_payload_json,
|
||||
playable_npc_count: input.playable_npc_count,
|
||||
landmark_count: input.landmark_count,
|
||||
author_display_name: input.author_display_name,
|
||||
updated_at_micros: input.updated_at_micros,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_profile_list_result(
|
||||
result: CustomWorldProfileListResult,
|
||||
) -> Result<Vec<CustomWorldLibraryEntryRecord>, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result
|
||||
.entries
|
||||
.into_iter()
|
||||
.map(map_custom_world_library_entry_from_profile_snapshot)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_library_detail_result(
|
||||
result: CustomWorldLibraryMutationResult,
|
||||
) -> Result<CustomWorldLibraryMutationRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let entry = result
|
||||
.entry
|
||||
.ok_or_else(|| SpacetimeClientError::Procedure("custom_world_profile 不存在".to_string()))
|
||||
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
|
||||
let gallery_entry = result
|
||||
.gallery_entry
|
||||
.map(map_custom_world_gallery_entry_snapshot)
|
||||
.transpose()?;
|
||||
|
||||
Ok(CustomWorldLibraryMutationRecord {
|
||||
entry,
|
||||
gallery_entry,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_gallery_list_result(
|
||||
result: CustomWorldGalleryListResult,
|
||||
) -> Result<Vec<CustomWorldGalleryEntryRecord>, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
Ok(result
|
||||
.entries
|
||||
.into_iter()
|
||||
.map(map_custom_world_gallery_entry_snapshot)
|
||||
.collect::<Result<Vec<_>, _>>()?)
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_library_mutation_result(
|
||||
result: CustomWorldLibraryMutationResult,
|
||||
) -> Result<CustomWorldLibraryMutationRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let entry = result
|
||||
.entry
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world entry"))
|
||||
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
|
||||
let gallery_entry = result
|
||||
.gallery_entry
|
||||
.map(map_custom_world_gallery_entry_snapshot)
|
||||
.transpose()?;
|
||||
|
||||
Ok(CustomWorldLibraryMutationRecord {
|
||||
entry,
|
||||
gallery_entry,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_publish_world_result(
|
||||
result: CustomWorldPublishWorldResult,
|
||||
) -> Result<CustomWorldPublishWorldRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let compiled_record = result
|
||||
.compiled_record
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("published profile compile 快照"))
|
||||
.and_then(map_custom_world_published_profile_compile_snapshot)?;
|
||||
let entry = result
|
||||
.entry
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world entry"))
|
||||
.and_then(map_custom_world_library_entry_from_profile_snapshot)?;
|
||||
let gallery_entry = result
|
||||
.gallery_entry
|
||||
.map(map_custom_world_gallery_entry_snapshot)
|
||||
.transpose()?;
|
||||
let session_stage = result
|
||||
.session_stage
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("session stage"))
|
||||
.map(map_rpg_agent_stage)?;
|
||||
|
||||
Ok(CustomWorldPublishWorldRecord {
|
||||
compiled_record,
|
||||
entry,
|
||||
gallery_entry,
|
||||
session_stage,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_session_procedure_result(
|
||||
result: CustomWorldAgentSessionProcedureResult,
|
||||
) -> Result<CustomWorldAgentSessionRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let session = result
|
||||
.session
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world agent session 快照"))?;
|
||||
|
||||
map_custom_world_agent_session_snapshot(session)
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_operation_procedure_result(
|
||||
result: CustomWorldAgentOperationProcedureResult,
|
||||
) -> Result<CustomWorldAgentOperationRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let operation = result.operation.ok_or_else(|| {
|
||||
SpacetimeClientError::missing_snapshot("custom world agent operation 快照")
|
||||
})?;
|
||||
|
||||
Ok(map_custom_world_agent_operation_snapshot(operation))
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_works_list_result(
|
||||
result: CustomWorldWorksListResult,
|
||||
) -> Result<Vec<CustomWorldWorkSummaryRecord>, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result
|
||||
.items
|
||||
.into_iter()
|
||||
.map(map_custom_world_work_summary_snapshot)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_draft_card_detail_result(
|
||||
result: CustomWorldDraftCardDetailResult,
|
||||
) -> Result<CustomWorldDraftCardDetailRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let card = result
|
||||
.card
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("custom world card detail 快照"))?;
|
||||
|
||||
map_custom_world_draft_card_detail_snapshot(card)
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_action_execute_result(
|
||||
result: CustomWorldAgentActionExecuteResult,
|
||||
) -> Result<CustomWorldAgentActionExecuteRecord, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
let operation = result.operation.ok_or_else(|| {
|
||||
SpacetimeClientError::missing_snapshot("custom world action operation 快照")
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldAgentActionExecuteRecord {
|
||||
operation: map_custom_world_agent_operation_snapshot(operation),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_library_entry_from_profile_snapshot(
|
||||
snapshot: CustomWorldProfileSnapshot,
|
||||
) -> Result<CustomWorldLibraryEntryRecord, SpacetimeClientError> {
|
||||
let profile = serde_json::from_str::<serde_json::Value>(&snapshot.profile_payload_json)
|
||||
.map_err(|error| {
|
||||
SpacetimeClientError::Runtime(format!(
|
||||
"custom world profile payload JSON 非法: {error}"
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldLibraryEntryRecord {
|
||||
owner_user_id: snapshot.owner_user_id,
|
||||
profile_id: snapshot.profile_id,
|
||||
public_work_code: snapshot.public_work_code,
|
||||
author_public_user_code: snapshot.author_public_user_code,
|
||||
profile,
|
||||
visibility: map_custom_world_publication_status(snapshot.publication_status).to_string(),
|
||||
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
author_display_name: snapshot.author_display_name,
|
||||
world_name: snapshot.world_name,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary_text: snapshot.summary_text,
|
||||
cover_image_src: snapshot.cover_image_src,
|
||||
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
|
||||
snapshot.theme_mode,
|
||||
))
|
||||
.to_string(),
|
||||
playable_npc_count: snapshot.playable_npc_count,
|
||||
landmark_count: snapshot.landmark_count,
|
||||
play_count: snapshot.play_count,
|
||||
remix_count: snapshot.remix_count,
|
||||
like_count: snapshot.like_count,
|
||||
recent_play_count_7d: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_gallery_entry_snapshot(
|
||||
snapshot: CustomWorldGalleryEntrySnapshot,
|
||||
) -> Result<CustomWorldGalleryEntryRecord, SpacetimeClientError> {
|
||||
Ok(CustomWorldGalleryEntryRecord {
|
||||
owner_user_id: snapshot.owner_user_id,
|
||||
profile_id: snapshot.profile_id,
|
||||
public_work_code: snapshot.public_work_code,
|
||||
author_public_user_code: snapshot.author_public_user_code,
|
||||
visibility: "published".to_string(),
|
||||
published_at: Some(format_timestamp_micros(snapshot.published_at_micros)),
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
author_display_name: snapshot.author_display_name,
|
||||
world_name: snapshot.world_name,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary_text: snapshot.summary_text,
|
||||
cover_image_src: snapshot.cover_image_src,
|
||||
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
|
||||
snapshot.theme_mode,
|
||||
))
|
||||
.to_string(),
|
||||
playable_npc_count: snapshot.playable_npc_count,
|
||||
landmark_count: snapshot.landmark_count,
|
||||
play_count: snapshot.play_count,
|
||||
remix_count: snapshot.remix_count,
|
||||
like_count: snapshot.like_count,
|
||||
recent_play_count_7d: snapshot.recent_play_count_7_d,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_gallery_entry_row(
|
||||
row: CustomWorldGalleryEntry,
|
||||
recent_play_count_7d: u32,
|
||||
) -> CustomWorldGalleryEntryRecord {
|
||||
CustomWorldGalleryEntryRecord {
|
||||
owner_user_id: row.owner_user_id,
|
||||
profile_id: row.profile_id,
|
||||
public_work_code: row.public_work_code,
|
||||
author_public_user_code: row.author_public_user_code,
|
||||
visibility: "published".to_string(),
|
||||
published_at: Some(format_timestamp_micros(
|
||||
row.published_at.to_micros_since_unix_epoch(),
|
||||
)),
|
||||
updated_at: format_timestamp_micros(row.updated_at.to_micros_since_unix_epoch()),
|
||||
author_display_name: row.author_display_name,
|
||||
world_name: row.world_name,
|
||||
subtitle: row.subtitle,
|
||||
summary_text: row.summary_text,
|
||||
cover_image_src: row.cover_image_src,
|
||||
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
|
||||
row.theme_mode,
|
||||
))
|
||||
.to_string(),
|
||||
playable_npc_count: row.playable_npc_count,
|
||||
landmark_count: row.landmark_count,
|
||||
play_count: row.play_count,
|
||||
remix_count: row.remix_count,
|
||||
like_count: row.like_count,
|
||||
recent_play_count_7d,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_published_profile_compile_snapshot(
|
||||
snapshot: CustomWorldPublishedProfileCompileSnapshot,
|
||||
) -> Result<CustomWorldPublishedProfileCompileRecord, SpacetimeClientError> {
|
||||
let compiled_profile =
|
||||
serde_json::from_str::<serde_json::Value>(&snapshot.compiled_profile_payload_json)
|
||||
.map_err(|error| {
|
||||
SpacetimeClientError::Runtime(format!(
|
||||
"published profile compile JSON 非法: {error}"
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldPublishedProfileCompileRecord {
|
||||
profile_id: snapshot.profile_id,
|
||||
owner_user_id: snapshot.owner_user_id,
|
||||
world_name: snapshot.world_name,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary_text: snapshot.summary_text,
|
||||
theme_mode: format_custom_world_theme_mode(map_custom_world_theme_mode_back(
|
||||
snapshot.theme_mode,
|
||||
))
|
||||
.to_string(),
|
||||
cover_image_src: snapshot.cover_image_src,
|
||||
playable_npc_count: snapshot.playable_npc_count,
|
||||
landmark_count: snapshot.landmark_count,
|
||||
author_display_name: snapshot.author_display_name,
|
||||
compiled_profile: compiled_profile,
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_work_summary_snapshot(
|
||||
snapshot: CustomWorldWorkSummarySnapshot,
|
||||
) -> Result<CustomWorldWorkSummaryRecord, SpacetimeClientError> {
|
||||
Ok(CustomWorldWorkSummaryRecord {
|
||||
work_id: snapshot.work_id,
|
||||
source_type: snapshot.source_type,
|
||||
status: snapshot.status,
|
||||
title: snapshot.title,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary: snapshot.summary,
|
||||
cover_image_src: snapshot.cover_image_src,
|
||||
cover_render_mode: snapshot.cover_render_mode,
|
||||
cover_character_image_srcs: parse_json_string_array(
|
||||
&snapshot.cover_character_image_srcs_json,
|
||||
"custom world work cover_character_image_srcs_json",
|
||||
)?,
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
|
||||
stage: snapshot.stage.map(map_rpg_agent_stage),
|
||||
stage_label: snapshot.stage_label,
|
||||
playable_npc_count: snapshot.playable_npc_count,
|
||||
landmark_count: snapshot.landmark_count,
|
||||
role_visual_ready_count: snapshot.role_visual_ready_count,
|
||||
role_animation_ready_count: snapshot.role_animation_ready_count,
|
||||
role_asset_summary_label: snapshot.role_asset_summary_label,
|
||||
session_id: snapshot.session_id,
|
||||
profile_id: snapshot.profile_id,
|
||||
can_resume: snapshot.can_resume,
|
||||
can_enter_world: snapshot.can_enter_world,
|
||||
blocker_count: snapshot.blocker_count,
|
||||
publish_ready: snapshot.publish_ready,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_session_snapshot(
|
||||
snapshot: CustomWorldAgentSessionSnapshot,
|
||||
) -> Result<CustomWorldAgentSessionRecord, SpacetimeClientError> {
|
||||
let anchor_content = parse_json_value(
|
||||
&snapshot.anchor_content_json,
|
||||
"custom world agent anchor_content_json",
|
||||
)?;
|
||||
let creator_intent = parse_optional_json_value(
|
||||
snapshot.creator_intent_json.as_deref(),
|
||||
serde_json::json!({}),
|
||||
"custom world agent creator_intent_json",
|
||||
)?;
|
||||
let creator_intent_readiness = parse_json_value(
|
||||
&snapshot.creator_intent_readiness_json,
|
||||
"custom world agent creator_intent_readiness_json",
|
||||
)?;
|
||||
let anchor_pack = parse_optional_json_value(
|
||||
snapshot.anchor_pack_json.as_deref(),
|
||||
serde_json::json!({}),
|
||||
"custom world agent anchor_pack_json",
|
||||
)?;
|
||||
let lock_state = parse_optional_json_value(
|
||||
snapshot.lock_state_json.as_deref(),
|
||||
serde_json::json!({}),
|
||||
"custom world agent lock_state_json",
|
||||
)?;
|
||||
let draft_profile = parse_optional_json_value(
|
||||
snapshot.draft_profile_json.as_deref(),
|
||||
serde_json::json!({}),
|
||||
"custom world agent draft_profile_json",
|
||||
)?;
|
||||
let pending_clarifications = parse_json_array(
|
||||
&snapshot.pending_clarifications_json,
|
||||
"custom world agent pending_clarifications_json",
|
||||
)?;
|
||||
let suggested_actions = parse_json_array(
|
||||
&snapshot.suggested_actions_json,
|
||||
"custom world agent suggested_actions_json",
|
||||
)?;
|
||||
let recommended_replies = parse_json_string_array(
|
||||
&snapshot.recommended_replies_json,
|
||||
"custom world agent recommended_replies_json",
|
||||
)?;
|
||||
let quality_findings = parse_json_array(
|
||||
&snapshot.quality_findings_json,
|
||||
"custom world agent quality_findings_json",
|
||||
)?;
|
||||
let asset_coverage = parse_json_value(
|
||||
&snapshot.asset_coverage_json,
|
||||
"custom world agent asset_coverage_json",
|
||||
)?;
|
||||
let checkpoints_json = parse_json_array(
|
||||
&snapshot.checkpoints_json,
|
||||
"custom world agent checkpoints_json",
|
||||
)?;
|
||||
let checkpoints = checkpoints_json
|
||||
.into_iter()
|
||||
.map(map_custom_world_checkpoint_record)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let supported_actions = parse_supported_actions_json(&snapshot.supported_actions_json)?;
|
||||
let publish_gate = snapshot
|
||||
.publish_gate_json
|
||||
.as_deref()
|
||||
.map(parse_custom_world_publish_gate_record)
|
||||
.transpose()?;
|
||||
|
||||
Ok(CustomWorldAgentSessionRecord {
|
||||
session_id: snapshot.session_id,
|
||||
seed_text: snapshot.seed_text,
|
||||
current_turn: snapshot.current_turn,
|
||||
anchor_content,
|
||||
progress_percent: snapshot.progress_percent,
|
||||
last_assistant_reply: snapshot.last_assistant_reply,
|
||||
stage: map_rpg_agent_stage(snapshot.stage),
|
||||
focus_card_id: snapshot.focus_card_id,
|
||||
creator_intent,
|
||||
creator_intent_readiness,
|
||||
anchor_pack,
|
||||
lock_state,
|
||||
draft_profile,
|
||||
messages: snapshot
|
||||
.messages
|
||||
.into_iter()
|
||||
.map(map_custom_world_agent_message_snapshot)
|
||||
.collect(),
|
||||
draft_cards: snapshot
|
||||
.draft_cards
|
||||
.into_iter()
|
||||
.map(map_custom_world_draft_card_snapshot)
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
pending_clarifications,
|
||||
suggested_actions,
|
||||
recommended_replies,
|
||||
quality_findings,
|
||||
asset_coverage,
|
||||
checkpoints,
|
||||
supported_actions,
|
||||
publish_gate,
|
||||
result_preview: snapshot
|
||||
.result_preview_json
|
||||
.as_deref()
|
||||
.map(|value| parse_json_value(value, "custom world agent result_preview_json"))
|
||||
.transpose()?,
|
||||
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_message_snapshot(
|
||||
snapshot: CustomWorldAgentMessageSnapshot,
|
||||
) -> CustomWorldAgentMessageRecord {
|
||||
CustomWorldAgentMessageRecord {
|
||||
message_id: snapshot.message_id,
|
||||
role: format_rpg_agent_message_role(snapshot.role).to_string(),
|
||||
kind: format_rpg_agent_message_kind(snapshot.kind).to_string(),
|
||||
text: snapshot.text,
|
||||
created_at: format_timestamp_micros(snapshot.created_at_micros),
|
||||
related_operation_id: snapshot.related_operation_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_agent_operation_snapshot(
|
||||
snapshot: CustomWorldAgentOperationSnapshot,
|
||||
) -> CustomWorldAgentOperationRecord {
|
||||
CustomWorldAgentOperationRecord {
|
||||
operation_id: snapshot.operation_id,
|
||||
operation_type: format_rpg_agent_operation_type(snapshot.operation_type).to_string(),
|
||||
status: format_rpg_agent_operation_status(snapshot.status).to_string(),
|
||||
phase_label: snapshot.phase_label,
|
||||
phase_detail: snapshot.phase_detail,
|
||||
progress: snapshot.progress,
|
||||
error_message: snapshot.error_message,
|
||||
started_at_micros: snapshot.created_at_micros,
|
||||
updated_at_micros: snapshot.updated_at_micros,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_draft_card_snapshot(
|
||||
snapshot: CustomWorldDraftCardSnapshot,
|
||||
) -> Result<CustomWorldDraftCardRecord, SpacetimeClientError> {
|
||||
Ok(CustomWorldDraftCardRecord {
|
||||
card_id: snapshot.card_id,
|
||||
kind: format_rpg_agent_draft_card_kind(snapshot.kind).to_string(),
|
||||
title: snapshot.title,
|
||||
subtitle: snapshot.subtitle,
|
||||
summary: snapshot.summary,
|
||||
status: format_rpg_agent_draft_card_status(snapshot.status).to_string(),
|
||||
linked_ids: parse_json_string_array(
|
||||
&snapshot.linked_ids_json,
|
||||
"custom world draft_card linked_ids_json",
|
||||
)?,
|
||||
warning_count: snapshot.warning_count,
|
||||
asset_status: snapshot
|
||||
.asset_status
|
||||
.map(format_custom_world_role_asset_status_back),
|
||||
asset_status_label: snapshot.asset_status_label,
|
||||
detail_payload: snapshot
|
||||
.detail_payload_json
|
||||
.as_deref()
|
||||
.map(|value| parse_json_value(value, "custom world draft_card detail_payload_json"))
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_draft_card_detail_snapshot(
|
||||
snapshot: CustomWorldDraftCardDetailSnapshot,
|
||||
) -> Result<CustomWorldDraftCardDetailRecord, SpacetimeClientError> {
|
||||
Ok(CustomWorldDraftCardDetailRecord {
|
||||
card_id: snapshot.card_id,
|
||||
kind: format_rpg_agent_draft_card_kind(snapshot.kind).to_string(),
|
||||
title: snapshot.title,
|
||||
sections: snapshot
|
||||
.sections
|
||||
.into_iter()
|
||||
.map(map_custom_world_draft_card_detail_section_snapshot)
|
||||
.collect(),
|
||||
linked_ids: parse_json_string_array(
|
||||
&snapshot.linked_ids_json,
|
||||
"custom world card detail linked_ids_json",
|
||||
)?,
|
||||
locked: snapshot.locked,
|
||||
editable: snapshot.editable,
|
||||
editable_section_ids: parse_json_string_array(
|
||||
&snapshot.editable_section_ids_json,
|
||||
"custom world card detail editable_section_ids_json",
|
||||
)?,
|
||||
warning_messages: parse_json_string_array(
|
||||
&snapshot.warning_messages_json,
|
||||
"custom world card detail warning_messages_json",
|
||||
)?,
|
||||
asset_status: snapshot
|
||||
.asset_status
|
||||
.map(format_custom_world_role_asset_status_back),
|
||||
asset_status_label: snapshot.asset_status_label,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_draft_card_detail_section_snapshot(
|
||||
snapshot: CustomWorldDraftCardDetailSectionSnapshot,
|
||||
) -> CustomWorldDraftCardDetailSectionRecord {
|
||||
CustomWorldDraftCardDetailSectionRecord {
|
||||
section_id: snapshot.section_id,
|
||||
label: snapshot.label,
|
||||
value: snapshot.value,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_theme_mode(
|
||||
value: DomainCustomWorldThemeMode,
|
||||
) -> CustomWorldThemeMode {
|
||||
match value {
|
||||
DomainCustomWorldThemeMode::Martial => CustomWorldThemeMode::Martial,
|
||||
DomainCustomWorldThemeMode::Arcane => CustomWorldThemeMode::Arcane,
|
||||
DomainCustomWorldThemeMode::Machina => CustomWorldThemeMode::Machina,
|
||||
DomainCustomWorldThemeMode::Tide => CustomWorldThemeMode::Tide,
|
||||
DomainCustomWorldThemeMode::Rift => CustomWorldThemeMode::Rift,
|
||||
DomainCustomWorldThemeMode::Mythic => CustomWorldThemeMode::Mythic,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_theme_mode_back(
|
||||
value: CustomWorldThemeMode,
|
||||
) -> DomainCustomWorldThemeMode {
|
||||
match value {
|
||||
CustomWorldThemeMode::Martial => DomainCustomWorldThemeMode::Martial,
|
||||
CustomWorldThemeMode::Arcane => DomainCustomWorldThemeMode::Arcane,
|
||||
CustomWorldThemeMode::Machina => DomainCustomWorldThemeMode::Machina,
|
||||
CustomWorldThemeMode::Tide => DomainCustomWorldThemeMode::Tide,
|
||||
CustomWorldThemeMode::Rift => DomainCustomWorldThemeMode::Rift,
|
||||
CustomWorldThemeMode::Mythic => DomainCustomWorldThemeMode::Mythic,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_publication_status(
|
||||
value: CustomWorldPublicationStatus,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
CustomWorldPublicationStatus::Draft => "draft",
|
||||
CustomWorldPublicationStatus::Published => "published",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_rpg_agent_stage(value: crate::module_bindings::RpgAgentStage) -> String {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentStage::CollectingIntent => "collecting_intent",
|
||||
crate::module_bindings::RpgAgentStage::Clarifying => "clarifying",
|
||||
crate::module_bindings::RpgAgentStage::FoundationReview => "foundation_review",
|
||||
crate::module_bindings::RpgAgentStage::ObjectRefining => "object_refining",
|
||||
crate::module_bindings::RpgAgentStage::VisualRefining => "visual_refining",
|
||||
crate::module_bindings::RpgAgentStage::LongTailReview => "long_tail_review",
|
||||
crate::module_bindings::RpgAgentStage::ReadyToPublish => "ready_to_publish",
|
||||
crate::module_bindings::RpgAgentStage::Published => "published",
|
||||
crate::module_bindings::RpgAgentStage::Error => "error",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub(crate) fn parse_rpg_agent_stage_record(
|
||||
value: &str,
|
||||
) -> Result<crate::module_bindings::RpgAgentStage, SpacetimeClientError> {
|
||||
match value.trim() {
|
||||
"collecting_intent" => Ok(crate::module_bindings::RpgAgentStage::CollectingIntent),
|
||||
"clarifying" => Ok(crate::module_bindings::RpgAgentStage::Clarifying),
|
||||
"foundation_review" => Ok(crate::module_bindings::RpgAgentStage::FoundationReview),
|
||||
"object_refining" => Ok(crate::module_bindings::RpgAgentStage::ObjectRefining),
|
||||
"visual_refining" => Ok(crate::module_bindings::RpgAgentStage::VisualRefining),
|
||||
"long_tail_review" => Ok(crate::module_bindings::RpgAgentStage::LongTailReview),
|
||||
"ready_to_publish" => Ok(crate::module_bindings::RpgAgentStage::ReadyToPublish),
|
||||
"published" => Ok(crate::module_bindings::RpgAgentStage::Published),
|
||||
"error" => Ok(crate::module_bindings::RpgAgentStage::Error),
|
||||
other => Err(SpacetimeClientError::Runtime(format!(
|
||||
"未知 rpg agent stage: {other}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_message_role(
|
||||
value: crate::module_bindings::RpgAgentMessageRole,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentMessageRole::User => "user",
|
||||
crate::module_bindings::RpgAgentMessageRole::Assistant => "assistant",
|
||||
crate::module_bindings::RpgAgentMessageRole::System => "system",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_message_kind(
|
||||
value: crate::module_bindings::RpgAgentMessageKind,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentMessageKind::Chat => "chat",
|
||||
crate::module_bindings::RpgAgentMessageKind::Clarification => "clarification",
|
||||
crate::module_bindings::RpgAgentMessageKind::Summary => "summary",
|
||||
crate::module_bindings::RpgAgentMessageKind::Checkpoint => "checkpoint",
|
||||
crate::module_bindings::RpgAgentMessageKind::Warning => "warning",
|
||||
crate::module_bindings::RpgAgentMessageKind::ActionResult => "action_result",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_operation_type(
|
||||
value: crate::module_bindings::RpgAgentOperationType,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentOperationType::ProcessMessage => "process_message",
|
||||
crate::module_bindings::RpgAgentOperationType::DraftFoundation => "draft_foundation",
|
||||
crate::module_bindings::RpgAgentOperationType::UpdateDraftCard => "update_draft_card",
|
||||
crate::module_bindings::RpgAgentOperationType::SyncResultProfile => "sync_result_profile",
|
||||
crate::module_bindings::RpgAgentOperationType::GenerateCharacters => "generate_characters",
|
||||
crate::module_bindings::RpgAgentOperationType::GenerateLandmarks => "generate_landmarks",
|
||||
crate::module_bindings::RpgAgentOperationType::GenerateRoleAssets => "generate_role_assets",
|
||||
crate::module_bindings::RpgAgentOperationType::SyncRoleAssets => "sync_role_assets",
|
||||
crate::module_bindings::RpgAgentOperationType::GenerateSceneAssets => {
|
||||
"generate_scene_assets"
|
||||
}
|
||||
crate::module_bindings::RpgAgentOperationType::SyncSceneAssets => "sync_scene_assets",
|
||||
crate::module_bindings::RpgAgentOperationType::ExpandLongTail => "expand_long_tail",
|
||||
crate::module_bindings::RpgAgentOperationType::PublishWorld => "publish_world",
|
||||
crate::module_bindings::RpgAgentOperationType::RevertCheckpoint => "revert_checkpoint",
|
||||
crate::module_bindings::RpgAgentOperationType::DeleteCharacters => "delete_characters",
|
||||
crate::module_bindings::RpgAgentOperationType::DeleteLandmarks => "delete_landmarks",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_rpg_agent_operation_type_record(
|
||||
value: &str,
|
||||
) -> Result<crate::module_bindings::RpgAgentOperationType, SpacetimeClientError> {
|
||||
match value.trim() {
|
||||
"process_message" => Ok(crate::module_bindings::RpgAgentOperationType::ProcessMessage),
|
||||
"draft_foundation" => Ok(crate::module_bindings::RpgAgentOperationType::DraftFoundation),
|
||||
"update_draft_card" => Ok(crate::module_bindings::RpgAgentOperationType::UpdateDraftCard),
|
||||
"sync_result_profile" => {
|
||||
Ok(crate::module_bindings::RpgAgentOperationType::SyncResultProfile)
|
||||
}
|
||||
"generate_characters" => {
|
||||
Ok(crate::module_bindings::RpgAgentOperationType::GenerateCharacters)
|
||||
}
|
||||
"generate_landmarks" => {
|
||||
Ok(crate::module_bindings::RpgAgentOperationType::GenerateLandmarks)
|
||||
}
|
||||
"generate_role_assets" => {
|
||||
Ok(crate::module_bindings::RpgAgentOperationType::GenerateRoleAssets)
|
||||
}
|
||||
"sync_role_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncRoleAssets),
|
||||
"generate_scene_assets" => {
|
||||
Ok(crate::module_bindings::RpgAgentOperationType::GenerateSceneAssets)
|
||||
}
|
||||
"sync_scene_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncSceneAssets),
|
||||
"expand_long_tail" => Ok(crate::module_bindings::RpgAgentOperationType::ExpandLongTail),
|
||||
"publish_world" => Ok(crate::module_bindings::RpgAgentOperationType::PublishWorld),
|
||||
"revert_checkpoint" => Ok(crate::module_bindings::RpgAgentOperationType::RevertCheckpoint),
|
||||
"delete_characters" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteCharacters),
|
||||
"delete_landmarks" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteLandmarks),
|
||||
other => Err(SpacetimeClientError::Runtime(format!(
|
||||
"未知 rpg agent operation type: {other}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_operation_status(
|
||||
value: crate::module_bindings::RpgAgentOperationStatus,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentOperationStatus::Queued => "queued",
|
||||
crate::module_bindings::RpgAgentOperationStatus::Running => "running",
|
||||
crate::module_bindings::RpgAgentOperationStatus::Completed => "completed",
|
||||
crate::module_bindings::RpgAgentOperationStatus::Failed => "failed",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_rpg_agent_operation_status_record(
|
||||
value: &str,
|
||||
) -> Result<crate::module_bindings::RpgAgentOperationStatus, SpacetimeClientError> {
|
||||
match value.trim() {
|
||||
"queued" => Ok(crate::module_bindings::RpgAgentOperationStatus::Queued),
|
||||
"running" => Ok(crate::module_bindings::RpgAgentOperationStatus::Running),
|
||||
"completed" => Ok(crate::module_bindings::RpgAgentOperationStatus::Completed),
|
||||
"failed" => Ok(crate::module_bindings::RpgAgentOperationStatus::Failed),
|
||||
other => Err(SpacetimeClientError::Runtime(format!(
|
||||
"未知 rpg agent operation status: {other}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_draft_card_kind(
|
||||
value: crate::module_bindings::RpgAgentDraftCardKind,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentDraftCardKind::World => "world",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Camp => "camp",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Faction => "faction",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Character => "character",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Landmark => "landmark",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Thread => "thread",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Chapter => "chapter",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::SceneChapter => "scene_chapter",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::Carrier => "carrier",
|
||||
crate::module_bindings::RpgAgentDraftCardKind::SidequestSeed => "sidequest_seed",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_rpg_agent_draft_card_status(
|
||||
value: crate::module_bindings::RpgAgentDraftCardStatus,
|
||||
) -> &'static str {
|
||||
match value {
|
||||
crate::module_bindings::RpgAgentDraftCardStatus::Suggested => "suggested",
|
||||
crate::module_bindings::RpgAgentDraftCardStatus::Confirmed => "confirmed",
|
||||
crate::module_bindings::RpgAgentDraftCardStatus::Locked => "locked",
|
||||
crate::module_bindings::RpgAgentDraftCardStatus::Warning => "warning",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_custom_world_role_asset_status_back(
|
||||
value: crate::module_bindings::CustomWorldRoleAssetStatus,
|
||||
) -> String {
|
||||
match value {
|
||||
crate::module_bindings::CustomWorldRoleAssetStatus::Missing => "missing",
|
||||
crate::module_bindings::CustomWorldRoleAssetStatus::VisualReady => "visual_ready",
|
||||
crate::module_bindings::CustomWorldRoleAssetStatus::AnimationsReady => "animations_ready",
|
||||
crate::module_bindings::CustomWorldRoleAssetStatus::Complete => "complete",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub(crate) fn format_custom_world_theme_mode(value: DomainCustomWorldThemeMode) -> &'static str {
|
||||
match value {
|
||||
DomainCustomWorldThemeMode::Martial => "martial",
|
||||
DomainCustomWorldThemeMode::Arcane => "arcane",
|
||||
DomainCustomWorldThemeMode::Machina => "machina",
|
||||
DomainCustomWorldThemeMode::Tide => "tide",
|
||||
DomainCustomWorldThemeMode::Rift => "rift",
|
||||
DomainCustomWorldThemeMode::Mythic => "mythic",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_ai_task_kind(value: AiTaskKind) -> &'static str {
|
||||
match value {
|
||||
AiTaskKind::StoryGeneration => "story_generation",
|
||||
AiTaskKind::CharacterChat => "character_chat",
|
||||
AiTaskKind::NpcChat => "npc_chat",
|
||||
AiTaskKind::CustomWorldGeneration => "custom_world_generation",
|
||||
AiTaskKind::QuestIntent => "quest_intent",
|
||||
AiTaskKind::RuntimeItemIntent => "runtime_item_intent",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_ai_result_reference_kind(value: AiResultReferenceKind) -> &'static str {
|
||||
match value {
|
||||
AiResultReferenceKind::StorySession => "story_session",
|
||||
AiResultReferenceKind::StoryEvent => "story_event",
|
||||
AiResultReferenceKind::CustomWorldProfile => "custom_world_profile",
|
||||
AiResultReferenceKind::QuestRecord => "quest_record",
|
||||
AiResultReferenceKind::RuntimeItemRecord => "runtime_item_record",
|
||||
AiResultReferenceKind::AssetObject => "asset_object",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_custom_world_checkpoint_record(
|
||||
value: serde_json::Value,
|
||||
) -> Result<CustomWorldCheckpointRecord, SpacetimeClientError> {
|
||||
let object = value.as_object().ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world checkpoint 必须是 JSON object".to_string())
|
||||
})?;
|
||||
let checkpoint_id = object
|
||||
.get("checkpointId")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world checkpoint.checkpointId 缺失".to_string())
|
||||
})?;
|
||||
let created_at = object
|
||||
.get("createdAt")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world checkpoint.createdAt 缺失".to_string())
|
||||
})?;
|
||||
let label = object
|
||||
.get("label")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world checkpoint.label 缺失".to_string())
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldCheckpointRecord {
|
||||
checkpoint_id: checkpoint_id.to_string(),
|
||||
created_at: created_at.to_string(),
|
||||
label: label.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn parse_custom_world_publish_gate_record(
|
||||
value: &str,
|
||||
) -> Result<CustomWorldPublishGateRecord, SpacetimeClientError> {
|
||||
let object = parse_json_value(value, "custom world publish_gate_json")?
|
||||
.as_object()
|
||||
.cloned()
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish_gate_json 必须是 JSON object".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let profile_id = object
|
||||
.get("profileId")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world publish_gate.profileId 缺失".to_string())
|
||||
})?;
|
||||
let blockers = object
|
||||
.get("blockers")
|
||||
.and_then(serde_json::Value::as_array)
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world publish_gate.blockers 缺失".to_string())
|
||||
})?
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|entry| {
|
||||
let object = entry.as_object().ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish gate blocker 必须是 JSON object".to_string(),
|
||||
)
|
||||
})?;
|
||||
let id = object
|
||||
.get("id")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish gate blocker.id 缺失".to_string(),
|
||||
)
|
||||
})?;
|
||||
let code = object
|
||||
.get("code")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish gate blocker.code 缺失".to_string(),
|
||||
)
|
||||
})?;
|
||||
let message = object
|
||||
.get("message")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish gate blocker.message 缺失".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldResultPreviewBlockerRecord {
|
||||
id: id.to_string(),
|
||||
code: code.to_string(),
|
||||
message: message.to_string(),
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let blocker_count = object
|
||||
.get("blockerCount")
|
||||
.and_then(serde_json::Value::as_u64)
|
||||
.and_then(|value| u32::try_from(value).ok())
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world publish_gate.blockerCount 缺失".to_string())
|
||||
})?;
|
||||
let publish_ready = object
|
||||
.get("publishReady")
|
||||
.and_then(serde_json::Value::as_bool)
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime("custom world publish_gate.publishReady 缺失".to_string())
|
||||
})?;
|
||||
let can_enter_world = object
|
||||
.get("canEnterWorld")
|
||||
.and_then(serde_json::Value::as_bool)
|
||||
.ok_or_else(|| {
|
||||
SpacetimeClientError::Runtime(
|
||||
"custom world publish_gate.canEnterWorld 缺失".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(CustomWorldPublishGateRecord {
|
||||
profile_id: profile_id.to_string(),
|
||||
blockers,
|
||||
blocker_count,
|
||||
publish_ready,
|
||||
can_enter_world,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user