Resolve spacetime client binding merge conflicts

This commit is contained in:
2026-04-24 14:44:46 +08:00
parent 4f369617c7
commit f65177b147
26 changed files with 2172 additions and 1020 deletions

View File

@@ -29,10 +29,10 @@ use shared_kernel::build_prefixed_uuid_id;
use spacetime_client::{
CustomWorldAgentActionExecuteRecordInput, CustomWorldAgentCheckpointRecord,
CustomWorldAgentMessageRecord, CustomWorldAgentMessageSubmitRecordInput,
CustomWorldAgentOperationRecord, CustomWorldAgentSessionCreateRecordInput,
CustomWorldAgentSessionRecord, CustomWorldDraftCardDetailRecord,
CustomWorldDraftCardDetailSectionRecord, CustomWorldDraftCardRecord,
CustomWorldGalleryEntryRecord, CustomWorldLibraryEntryRecord,
CustomWorldAgentOperationProgressRecordInput, CustomWorldAgentOperationRecord,
CustomWorldAgentSessionCreateRecordInput, CustomWorldAgentSessionRecord,
CustomWorldDraftCardDetailRecord, CustomWorldDraftCardDetailSectionRecord,
CustomWorldDraftCardRecord, CustomWorldGalleryEntryRecord, CustomWorldLibraryEntryRecord,
CustomWorldProfileUpsertRecordInput, CustomWorldPublishGateRecord,
CustomWorldResultPreviewBlockerRecord, CustomWorldSupportedActionRecord,
CustomWorldWorkSummaryRecord, SpacetimeClientError,
@@ -925,39 +925,44 @@ pub async fn execute_custom_world_agent_action(
})),
));
}
let draft_result = generate_custom_world_foundation_draft(llm_client, &session)
let operation_id = build_prefixed_uuid_id("operation-");
let operation = state
.spacetime_client()
.upsert_custom_world_agent_operation_progress(
CustomWorldAgentOperationProgressRecordInput {
session_id: session_id.clone(),
owner_user_id: owner_user_id.clone(),
operation_id: operation_id.clone(),
operation_type: "draft_foundation".to_string(),
operation_status: "running".to_string(),
phase_label: "整理世界骨架".to_string(),
phase_detail: "正在校验已确认锚点,并准备第一版世界框架生成链路。"
.to_string(),
operation_progress: 12,
error_message: None,
updated_at_micros: submitted_at_micros,
},
)
.await
.map_err(|message| {
.map_err(|error| {
custom_world_error_response(
&request_context,
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
"provider": "custom-world-agent",
"message": message,
})),
map_custom_world_client_error(error),
)
})?;
build_draft_foundation_action_payload_json(&payload, &draft_result.draft_profile_json)
.map_err(|error| {
let (status, message) = match error {
DraftFoundationPayloadError::SerializePayload(message) => {
(StatusCode::BAD_REQUEST, message)
}
DraftFoundationPayloadError::InvalidPayloadShape => (
StatusCode::BAD_REQUEST,
"action payload 必须是 object".to_string(),
),
DraftFoundationPayloadError::InvalidGeneratedDraft(message) => {
(StatusCode::BAD_GATEWAY, message)
}
};
custom_world_error_response(
&request_context,
AppError::from_status(status).with_details(json!({
"provider": "custom-world-agent",
"message": message,
})),
)
})?
spawn_custom_world_draft_foundation_job(
state.clone(),
session,
owner_user_id,
operation_id,
payload,
);
return Ok(json_success_body(
Some(&request_context),
json!({
"operation": map_custom_world_agent_operation_response(operation),
}),
));
} else {
let generation_result =
generate_custom_world_agent_entities(llm_client, &session, &payload)
@@ -1021,6 +1026,177 @@ pub async fn execute_custom_world_agent_action(
))
}
fn spawn_custom_world_draft_foundation_job(
state: AppState,
session: CustomWorldAgentSessionRecord,
owner_user_id: String,
operation_id: String,
payload: ExecuteCustomWorldAgentActionRequest,
) {
tokio::spawn(async move {
let Some(llm_client) = state.llm_client().cloned() else {
let _ = upsert_custom_world_draft_foundation_progress(
&state,
&session.session_id,
&owner_user_id,
&operation_id,
"failed",
"底稿生成失败",
"服务端尚未配置可用的 LLM API Key",
100,
Some("服务端尚未配置可用的 LLM API Key".to_string()),
)
.await;
return;
};
let progress_state = state.clone();
let progress_session_id = session.session_id.clone();
let progress_owner_user_id = owner_user_id.clone();
let progress_operation_id = operation_id.clone();
let draft_result =
generate_custom_world_foundation_draft(&llm_client, &session, move |progress| {
let progress_state = progress_state.clone();
let session_id = progress_session_id.clone();
let owner_user_id = progress_owner_user_id.clone();
let operation_id = progress_operation_id.clone();
tokio::spawn(async move {
let _ = upsert_custom_world_draft_foundation_progress(
&progress_state,
&session_id,
&owner_user_id,
&operation_id,
"running",
progress.phase_label.as_str(),
progress.phase_detail.as_str(),
progress.progress,
None,
)
.await;
});
})
.await;
let draft_result = match draft_result {
Ok(result) => result,
Err(message) => {
let _ = upsert_custom_world_draft_foundation_progress(
&state,
&session.session_id,
&owner_user_id,
&operation_id,
"failed",
"底稿生成失败",
message.clone().as_str(),
100,
Some(message),
)
.await;
return;
}
};
let _ = upsert_custom_world_draft_foundation_progress(
&state,
&session.session_id,
&owner_user_id,
&operation_id,
"running",
"编译草稿卡",
"正在把世界底稿整理成可浏览的卡片摘要和详情结构。",
98,
None,
)
.await;
let payload_json = match build_draft_foundation_action_payload_json(
&payload,
&draft_result.draft_profile_json,
) {
Ok(value) => value,
Err(error) => {
let message = match error {
DraftFoundationPayloadError::SerializePayload(message) => message,
DraftFoundationPayloadError::InvalidPayloadShape => {
"action payload 必须是 object".to_string()
}
DraftFoundationPayloadError::InvalidGeneratedDraft(message) => message,
};
let _ = upsert_custom_world_draft_foundation_progress(
&state,
&session.session_id,
&owner_user_id,
&operation_id,
"failed",
"底稿写入失败",
message.clone().as_str(),
100,
Some(message),
)
.await;
return;
}
};
if let Err(error) = state
.spacetime_client()
.execute_custom_world_agent_action(CustomWorldAgentActionExecuteRecordInput {
session_id: session.session_id.clone(),
owner_user_id: owner_user_id.clone(),
operation_id: operation_id.clone(),
action: "draft_foundation".to_string(),
payload_json: Some(payload_json),
submitted_at_micros: current_utc_micros(),
})
.await
{
let message = error.to_string();
let _ = upsert_custom_world_draft_foundation_progress(
&state,
&session.session_id,
&owner_user_id,
&operation_id,
"failed",
"底稿写入失败",
message.clone().as_str(),
100,
Some(message),
)
.await;
}
});
}
async fn upsert_custom_world_draft_foundation_progress(
state: &AppState,
session_id: &str,
owner_user_id: &str,
operation_id: &str,
status: &str,
phase_label: &str,
phase_detail: &str,
progress: u32,
error_message: Option<String>,
) -> Result<CustomWorldAgentOperationRecord, SpacetimeClientError> {
state
.spacetime_client()
.upsert_custom_world_agent_operation_progress(
CustomWorldAgentOperationProgressRecordInput {
session_id: session_id.to_string(),
owner_user_id: owner_user_id.to_string(),
operation_id: operation_id.to_string(),
operation_type: "draft_foundation".to_string(),
operation_status: status.to_string(),
phase_label: phase_label.to_string(),
phase_detail: phase_detail.to_string(),
operation_progress: progress.min(100),
error_message,
updated_at_micros: current_utc_micros(),
},
)
.await
}
fn map_custom_world_library_entry_response(
entry: CustomWorldLibraryEntryRecord,
) -> CustomWorldLibraryEntryResponse {