Extend square-hole creation flow with visual asset timeout guard

This commit is contained in:
kdletters
2026-05-05 15:27:09 +08:00
parent 2252afb080
commit 60b667a9d1
30 changed files with 2838 additions and 215 deletions

View File

@@ -55,11 +55,11 @@ pub use mapper::{
SquareHoleAgentMessageSubmitRecordInput, SquareHoleAgentSessionCreateRecordInput,
SquareHoleAgentSessionRecord, SquareHoleAnchorItemRecord, SquareHoleAnchorPackRecord,
SquareHoleCompileDraftRecordInput, SquareHoleCreatorConfigRecord,
SquareHoleDropConfirmationRecord, SquareHoleDropFeedbackRecord, SquareHoleHoleSnapshotRecord,
SquareHoleResultDraftRecord, SquareHoleRunDropRecordInput, SquareHoleRunRecord,
SquareHoleRunRestartRecordInput, SquareHoleRunStartRecordInput, SquareHoleRunStopRecordInput,
SquareHoleRunTimeUpRecordInput, SquareHoleShapeSnapshotRecord, SquareHoleWorkProfileRecord,
SquareHoleWorkUpdateRecordInput,
SquareHoleDropConfirmationRecord, SquareHoleDropFeedbackRecord, SquareHoleHoleOptionRecord,
SquareHoleHoleSnapshotRecord, SquareHoleResultDraftRecord, SquareHoleRunDropRecordInput,
SquareHoleRunRecord, SquareHoleRunRestartRecordInput, SquareHoleRunStartRecordInput,
SquareHoleRunStopRecordInput, SquareHoleRunTimeUpRecordInput, SquareHoleShapeOptionRecord,
SquareHoleShapeSnapshotRecord, SquareHoleWorkProfileRecord, SquareHoleWorkUpdateRecordInput,
};
pub mod ai;
@@ -144,9 +144,9 @@ use module_puzzle::{
PuzzleWorkProfile as DomainPuzzleWorkProfile,
};
use module_runtime::{
RuntimeBrowseHistoryRecord, RuntimePlatformTheme as DomainRuntimePlatformTheme,
RuntimeProfileDashboardRecord, RuntimeProfileInviteCodeRecord, RuntimeProfilePlayStatsRecord,
AnalyticsMetricQueryResponse as DomainAnalyticsMetricQueryResponse,
AnalyticsMetricQueryResponse as DomainAnalyticsMetricQueryResponse, RuntimeBrowseHistoryRecord,
RuntimePlatformTheme as DomainRuntimePlatformTheme, RuntimeProfileDashboardRecord,
RuntimeProfileInviteCodeRecord, RuntimeProfilePlayStatsRecord,
RuntimeProfileRechargeCenterRecord, RuntimeProfileRechargeOrderRecord,
RuntimeProfileRedeemCodeMode as DomainRuntimeProfileRedeemCodeMode,
RuntimeProfileRedeemCodeRecord, RuntimeProfileRewardCodeRedeemRecord,
@@ -155,7 +155,7 @@ use module_runtime::{
RuntimeProfileTaskStatus as DomainRuntimeProfileTaskStatus,
RuntimeProfileWalletLedgerEntryRecord, RuntimeReferralInviteCenterRecord,
RuntimeReferralRedeemRecord, RuntimeSettingsRecord, RuntimeSnapshotRecord,
RuntimeTrackingScopeKind as DomainRuntimeTrackingScopeKind,
RuntimeTrackingScopeKind as DomainRuntimeTrackingScopeKind, build_analytics_metric_query_input,
build_runtime_browse_history_clear_input, build_runtime_browse_history_list_input,
build_runtime_browse_history_record, build_runtime_browse_history_sync_input,
build_runtime_profile_dashboard_get_input, build_runtime_profile_dashboard_record,
@@ -178,7 +178,6 @@ use module_runtime::{
build_runtime_profile_wallet_adjustment_input,
build_runtime_profile_wallet_ledger_entry_record,
build_runtime_profile_wallet_ledger_list_input, build_runtime_referral_invite_center_get_input,
build_analytics_metric_query_input,
build_runtime_referral_invite_center_record, build_runtime_referral_redeem_input,
build_runtime_referral_redeem_record, build_runtime_setting_get_input,
build_runtime_setting_record, build_runtime_setting_upsert_input,

View File

@@ -1585,14 +1585,9 @@ pub(crate) fn map_square_hole_agent_session_procedure_result(
let session_json = result
.session_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole agent session 快照"))?;
let session =
serde_json::from_str::<SquareHoleAgentSessionJsonRecord>(&session_json).map_err(
|error| {
SpacetimeClientError::Runtime(format!(
"square hole session_json 非法: {error}"
))
},
)?;
let session = serde_json::from_str::<SquareHoleAgentSessionJsonRecord>(&session_json).map_err(
|error| SpacetimeClientError::Runtime(format!("square hole session_json 非法: {error}")),
)?;
Ok(map_square_hole_agent_session_snapshot(session))
}
@@ -1624,13 +1619,15 @@ pub(crate) fn map_square_hole_works_procedure_result(
let items_json = result
.items_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole works 快照"))?;
let items = serde_json::from_str::<Vec<SquareHoleWorkJsonRecord>>(&items_json).map_err(
|error| {
let items =
serde_json::from_str::<Vec<SquareHoleWorkJsonRecord>>(&items_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole works items_json 非法: {error}"))
},
)?;
})?;
Ok(items.into_iter().map(map_square_hole_work_snapshot).collect())
Ok(items
.into_iter()
.map(map_square_hole_work_snapshot)
.collect())
}
pub(crate) fn map_square_hole_run_procedure_result(
@@ -1656,18 +1653,14 @@ pub(crate) fn map_square_hole_drop_shape_procedure_result(
let run_json = result
.run_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop run 快照"))?;
let feedback_json = result.feedback_json.ok_or_else(|| {
SpacetimeClientError::missing_snapshot("square hole drop feedback 快照")
})?;
let feedback_json = result
.feedback_json
.ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop feedback 快照"))?;
let run = map_square_hole_run_json(run_json)?;
let feedback =
serde_json::from_str::<SquareHoleDropFeedbackJsonRecord>(&feedback_json).map_err(
|error| {
SpacetimeClientError::Runtime(format!(
"square hole feedback_json 非法: {error}"
))
},
)?;
let feedback = serde_json::from_str::<SquareHoleDropFeedbackJsonRecord>(&feedback_json)
.map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole feedback_json 非法: {error}"))
})?;
Ok(SquareHoleDropConfirmationRecord {
status: result.status,
@@ -2950,6 +2943,19 @@ fn map_square_hole_creator_config(
twist_rule: snapshot.twist_rule,
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
background_prompt: snapshot.background_prompt,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_image_src: empty_string_to_none(snapshot.background_image_src),
}
}
@@ -2963,6 +2969,19 @@ fn map_square_hole_result_draft(
twist_rule: snapshot.twist_rule,
summary: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_prompt: snapshot.background_prompt,
background_image_src: empty_string_to_none(snapshot.background_image_src),
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
publish_ready: false,
@@ -2997,6 +3016,18 @@ fn map_square_hole_work_snapshot(
summary: snapshot.summary_text,
tags: snapshot.tags,
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
background_prompt: snapshot.background_prompt,
background_image_src: empty_string_to_none(snapshot.background_image_src),
shape_options: snapshot
.shape_options
.into_iter()
.map(map_square_hole_shape_option)
.collect(),
hole_options: snapshot
.hole_options
.into_iter()
.map(map_square_hole_hole_option)
.collect(),
shape_count: snapshot.shape_count,
difficulty: snapshot.difficulty,
publication_status: normalize_square_hole_publication_status(&snapshot.publication_status)
@@ -3032,6 +3063,7 @@ fn map_square_hole_run_snapshot(snapshot: SquareHoleRunJsonRecord) -> SquareHole
best_combo: snapshot.best_combo,
score: snapshot.score,
rule_label: snapshot.rule_label,
background_image_src: empty_string_to_none(snapshot.background_image_src),
current_shape: snapshot.current_shape.map(map_square_hole_shape_snapshot),
holes: snapshot
.holes
@@ -3053,6 +3085,7 @@ fn map_square_hole_shape_snapshot(
shape_kind: snapshot.shape_kind,
label: snapshot.label,
color: snapshot.color,
image_src: empty_string_to_none(snapshot.image_src),
}
}
@@ -3065,6 +3098,30 @@ fn map_square_hole_hole_snapshot(
label: snapshot.label,
x: snapshot.x,
y: snapshot.y,
bonus: snapshot.bonus,
}
}
fn map_square_hole_shape_option(
snapshot: SquareHoleShapeOptionJsonRecord,
) -> SquareHoleShapeOptionRecord {
SquareHoleShapeOptionRecord {
option_id: snapshot.option_id,
shape_kind: snapshot.shape_kind,
label: snapshot.label,
image_prompt: snapshot.image_prompt,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_hole_option(
snapshot: SquareHoleHoleOptionJsonRecord,
) -> SquareHoleHoleOptionRecord {
SquareHoleHoleOptionRecord {
hole_id: snapshot.hole_id,
hole_kind: snapshot.hole_kind,
label: snapshot.label,
bonus: snapshot.bonus,
}
}
@@ -3087,7 +3144,11 @@ fn build_square_hole_anchor_pack(
let difficulty = config.difficulty.to_string();
SquareHoleAnchorPackRecord {
theme: build_square_hole_anchor_item("theme", "题材主题", config.theme_text.as_str()),
twist_rule: build_square_hole_anchor_item("twistRule", "反差规则", config.twist_rule.as_str()),
twist_rule: build_square_hole_anchor_item(
"twistRule",
"反差规则",
config.twist_rule.as_str(),
),
shape_count: build_square_hole_anchor_item("shapeCount", "形状数量", shape_count.as_str()),
difficulty: build_square_hole_anchor_item("difficulty", "难度", difficulty.as_str()),
}
@@ -5992,6 +6053,10 @@ pub struct SquareHoleWorkUpdateRecordInput {
pub summary_text: String,
pub tags_json: String,
pub cover_image_src: String,
pub background_prompt: String,
pub background_image_src: String,
pub shape_options_json: String,
pub hole_options_json: String,
pub shape_count: u32,
pub difficulty: u32,
pub updated_at_micros: i64,
@@ -6059,6 +6124,28 @@ pub struct SquareHoleCreatorConfigRecord {
pub twist_rule: String,
pub shape_count: u32,
pub difficulty: u32,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub background_prompt: String,
pub cover_image_src: Option<String>,
pub background_image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleShapeOptionRecord {
pub option_id: String,
pub shape_kind: String,
pub label: String,
pub image_prompt: String,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SquareHoleHoleOptionRecord {
pub hole_id: String,
pub hole_kind: String,
pub label: String,
pub bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -6069,6 +6156,11 @@ pub struct SquareHoleResultDraftRecord {
pub twist_rule: String,
pub summary: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub background_prompt: String,
pub background_image_src: Option<String>,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub shape_count: u32,
pub difficulty: u32,
pub publish_ready: bool,
@@ -6112,6 +6204,10 @@ pub struct SquareHoleWorkProfileRecord {
pub summary: String,
pub tags: Vec<String>,
pub cover_image_src: Option<String>,
pub background_prompt: String,
pub background_image_src: Option<String>,
pub shape_options: Vec<SquareHoleShapeOptionRecord>,
pub hole_options: Vec<SquareHoleHoleOptionRecord>,
pub shape_count: u32,
pub difficulty: u32,
pub publication_status: String,
@@ -6127,6 +6223,7 @@ pub struct SquareHoleShapeSnapshotRecord {
pub shape_kind: String,
pub label: String,
pub color: String,
pub image_src: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
@@ -6136,6 +6233,7 @@ pub struct SquareHoleHoleSnapshotRecord {
pub label: String,
pub x: f32,
pub y: f32,
pub bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -6162,6 +6260,7 @@ pub struct SquareHoleRunRecord {
pub best_combo: u32,
pub score: u32,
pub rule_label: String,
pub background_image_src: Option<String>,
pub current_shape: Option<SquareHoleShapeSnapshotRecord>,
pub holes: Vec<SquareHoleHoleSnapshotRecord>,
pub last_feedback: Option<SquareHoleDropFeedbackRecord>,
@@ -6185,6 +6284,37 @@ struct SquareHoleCreatorConfigJsonRecord {
twist_rule: String,
shape_count: u32,
difficulty: u32,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
#[serde(default)]
background_prompt: String,
#[serde(default)]
cover_image_src: String,
#[serde(default)]
background_image_src: String,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleShapeOptionJsonRecord {
option_id: String,
shape_kind: String,
label: String,
image_prompt: String,
#[serde(default)]
image_src: String,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct SquareHoleHoleOptionJsonRecord {
hole_id: String,
hole_kind: String,
label: String,
#[serde(default)]
bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
@@ -6208,6 +6338,16 @@ struct SquareHoleDraftJsonRecord {
twist_rule: String,
summary_text: String,
tags: Vec<String>,
#[serde(default)]
cover_image_src: String,
#[serde(default)]
background_prompt: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
shape_count: u32,
difficulty: u32,
}
@@ -6247,6 +6387,14 @@ struct SquareHoleWorkJsonRecord {
summary_text: String,
tags: Vec<String>,
cover_image_src: String,
#[serde(default)]
background_prompt: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
#[serde(default)]
hole_options: Vec<SquareHoleHoleOptionJsonRecord>,
shape_count: u32,
difficulty: u32,
#[allow(dead_code)]
@@ -6265,6 +6413,8 @@ struct SquareHoleShapeJsonRecord {
shape_kind: String,
label: String,
color: String,
#[serde(default)]
image_src: String,
}
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
@@ -6275,6 +6425,8 @@ struct SquareHoleHoleJsonRecord {
label: String,
x: f32,
y: f32,
#[serde(default)]
bonus: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
@@ -6303,6 +6455,11 @@ struct SquareHoleRunJsonRecord {
best_combo: u32,
score: u32,
rule_label: String,
#[serde(default)]
background_image_src: String,
#[serde(default)]
#[allow(dead_code)]
shape_options: Vec<SquareHoleShapeOptionJsonRecord>,
current_shape: Option<SquareHoleShapeJsonRecord>,
holes: Vec<SquareHoleHoleJsonRecord>,
last_feedback: Option<SquareHoleDropFeedbackJsonRecord>,

View File

@@ -15,6 +15,10 @@ pub struct SquareHoleWorkUpdateInput {
pub summary_text: String,
pub tags_json: String,
pub cover_image_src: String,
pub background_prompt: String,
pub background_image_src: String,
pub shape_options_json: String,
pub hole_options_json: String,
pub shape_count: u32,
pub difficulty: u32,
pub updated_at_micros: i64,

View File

@@ -17,15 +17,14 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection.procedures().create_square_hole_agent_session_then(
procedure_input,
move |_, result| {
connection
.procedures()
.create_square_hole_agent_session_then(procedure_input, move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_agent_session_procedure_result);
send_once(&sender, mapped);
},
);
});
})
.await
}
@@ -67,15 +66,14 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection.procedures().submit_square_hole_agent_message_then(
procedure_input,
move |_, result| {
connection
.procedures()
.submit_square_hole_agent_message_then(procedure_input, move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_agent_session_procedure_result);
send_once(&sender, mapped);
},
);
});
})
.await
}
@@ -126,14 +124,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.compile_square_hole_draft_then(procedure_input, move |_, result| {
connection.procedures().compile_square_hole_draft_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_agent_session_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -151,20 +150,25 @@ impl SpacetimeClient {
summary_text: input.summary_text,
tags_json: input.tags_json,
cover_image_src: input.cover_image_src,
background_prompt: input.background_prompt,
background_image_src: input.background_image_src,
shape_options_json: input.shape_options_json,
hole_options_json: input.hole_options_json,
shape_count: input.shape_count,
difficulty: input.difficulty,
updated_at_micros: input.updated_at_micros,
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.update_square_hole_work_then(procedure_input, move |_, result| {
connection.procedures().update_square_hole_work_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_work_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -182,14 +186,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.publish_square_hole_work_then(procedure_input, move |_, result| {
connection.procedures().publish_square_hole_work_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_work_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -221,14 +226,15 @@ impl SpacetimeClient {
procedure_input: SquareHoleWorksListInput,
) -> Result<Vec<SquareHoleWorkProfileRecord>, SpacetimeClientError> {
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.list_square_hole_works_then(procedure_input, move |_, result| {
connection.procedures().list_square_hole_works_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_works_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -244,14 +250,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.get_square_hole_work_detail_then(procedure_input, move |_, result| {
connection.procedures().get_square_hole_work_detail_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_work_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -267,14 +274,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.delete_square_hole_work_then(procedure_input, move |_, result| {
connection.procedures().delete_square_hole_work_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_works_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -291,14 +299,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.start_square_hole_run_then(procedure_input, move |_, result| {
connection.procedures().start_square_hole_run_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_run_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -341,21 +350,21 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.drop_square_hole_shape_then(procedure_input, move |_, result| {
connection.procedures().drop_square_hole_shape_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_drop_shape_procedure_result)
.map(|mut confirmation| {
if confirmation.accepted {
confirmation.run.last_confirmed_action_id =
Some(client_event_id);
confirmation.run.last_confirmed_action_id = Some(client_event_id);
}
confirmation
});
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -395,14 +404,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.restart_square_hole_run_then(procedure_input, move |_, result| {
connection.procedures().restart_square_hole_run_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_run_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}
@@ -418,14 +428,15 @@ impl SpacetimeClient {
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.finish_square_hole_time_up_then(procedure_input, move |_, result| {
connection.procedures().finish_square_hole_time_up_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_square_hole_run_procedure_result);
send_once(&sender, mapped);
});
},
);
})
.await
}