diff --git a/server-rs/crates/api-server/src/external_generation_worker.rs b/server-rs/crates/api-server/src/external_generation_worker.rs index f7e4f8f21..316e38ae4 100644 --- a/server-rs/crates/api-server/src/external_generation_worker.rs +++ b/server-rs/crates/api-server/src/external_generation_worker.rs @@ -1097,11 +1097,14 @@ fn editor_generation_result_payload_json( job: &ExternalGenerationJobRecord, response: &Value, ) -> String { + let warning = extract_editor_generation_slice_warning(response); + let response = compact_editor_generation_spritesheet_result(response); let mut payload = json!({ "sourceModule": job.source_module.clone(), "sourceEntityId": job.source_entity_id.clone(), + "response": response, }); - if let Some(warning) = extract_editor_generation_slice_warning(response) + if let Some(warning) = warning && let Some(object) = payload.as_object_mut() { object.insert("warning".to_string(), warning); @@ -1109,6 +1112,30 @@ fn editor_generation_result_payload_json( payload.to_string() } +fn compact_editor_generation_spritesheet_result(response: &Value) -> Value { + let data = response.get("data").unwrap_or(response); + let mut result = serde_json::Map::new(); + for field in [ + "spritesheetImageSrc", + "spritesheetWidth", + "spritesheetHeight", + "taskId", + ] { + if let Some(value) = data.get(field) { + result.insert(field.to_string(), value.clone()); + } + } + if let Some(resource) = data.get("spritesheetResource") { + let resource = compact_editor_generation_result(json!({ + "spritesheetResource": resource, + })); + if let Some(resource) = resource.get("spritesheetResource") { + result.insert("spritesheetResource".to_string(), resource.clone()); + } + } + Value::Object(result) +} + fn extract_editor_generation_slice_warning(response: &Value) -> Option { let data = response.get("data").unwrap_or(response); let warning = data.get("sliceWarning")?; @@ -1371,7 +1398,16 @@ mod tests { fn editor_generation_result_payload_keeps_only_lightweight_slice_warning() { let job = external_generation_job_record_fixture(Some("lease-1")); let response = json!({ - "spritesheetImageSrc": "data:image/png;base64,SHOULD_NOT_PERSIST", + "spritesheetImageSrc": "/api/assets/object/spritesheet.png", + "spritesheetWidth": 512, + "spritesheetHeight": 512, + "taskId": "task-1", + "spritesheetResource": { + "resourceId": "resource-1", + "objectKey": "spritesheet.png", + "assetObjectId": "asset-object-1", + "imageSrc": "data:image/png;base64,SHOULD_NOT_PERSIST" + }, "iconImageSrcs": [{"imageSrc": "data:image/png;base64,SHOULD_NOT_PERSIST"}], "sliceWarning": { "code": "insufficient-connected-components", @@ -1385,6 +1421,20 @@ mod tests { assert_eq!(payload["sourceModule"], json!("puzzle")); assert_eq!(payload["sourceEntityId"], json!("session-1:puzzle-level-1")); + assert_eq!( + payload["response"], + json!({ + "spritesheetImageSrc": "/api/assets/object/spritesheet.png", + "spritesheetWidth": 512, + "spritesheetHeight": 512, + "taskId": "task-1", + "spritesheetResource": { + "resourceId": "resource-1", + "objectKey": "spritesheet.png", + "assetObjectId": "asset-object-1" + } + }) + ); assert_eq!( payload["warning"], json!({ @@ -1392,8 +1442,7 @@ mod tests { "reason": "连通域数量不足" }) ); - assert!(payload.get("spritesheetImageSrc").is_none()); - assert!(payload.get("iconImageSrcs").is_none()); + assert!(!payload.to_string().contains("data:image")); } #[test] diff --git a/server-rs/crates/spacetime-module/src/external_generation.rs b/server-rs/crates/spacetime-module/src/external_generation.rs index 105db0900..3563cc8d6 100644 --- a/server-rs/crates/spacetime-module/src/external_generation.rs +++ b/server-rs/crates/spacetime-module/src/external_generation.rs @@ -869,8 +869,23 @@ fn get_external_generation_job_tx( ctx: &ReducerContext, input: ExternalGenerationJobGetInput, ) -> Result { - get_external_generation_job_summary_tx(ctx, input) - .map(map_external_generation_job_summary_to_compat_snapshot) + validate_required("external_generation_job.job_id", &input.job_id)?; + validate_required( + "external_generation_job.owner_user_id", + &input.owner_user_id, + )?; + let job_id = input.job_id.trim().to_string(); + let owner_user_id = input.owner_user_id.trim(); + let row = ctx + .db + .external_generation_job() + .job_id() + .find(&job_id) + .ok_or_else(|| "external_generation_job 不存在".to_string())?; + if row.owner_user_id.trim() != owner_user_id { + return Err("external_generation_job 不存在".to_string()); + } + Ok(map_external_generation_job_row(row)) } fn list_external_generation_jobs_tx(