diff --git a/server-rs/crates/api-server/src/editor_agent/api.rs b/server-rs/crates/api-server/src/editor_agent/api.rs index 13846f4ab..7588c4245 100644 --- a/server-rs/crates/api-server/src/editor_agent/api.rs +++ b/server-rs/crates/api-server/src/editor_agent/api.rs @@ -12,7 +12,6 @@ use module_editor_agent::{ use platform_llm::LlmMessage; use serde::Serialize; use serde_json::{json, Value}; -use sha2::{Digest, Sha256}; use shared_contracts::assets::{ EditorBackgroundMusicGenerateRequest, EditorSoundEffectGenerateRequest, EditorVideoGenerateRequest, @@ -57,7 +56,7 @@ use crate::editor_agent::utils::{ use crate::editor_agent::{context, display_args, reconcile}; use crate::editor_generation_config::EditorGenerationPricingConfig; use crate::editor_generation_queue::{ - enqueue_editor_generation_job_with_identity, EDITOR_BACKGROUND_MUSIC_GENERATION_JOB_KIND, + enqueue_editor_generation_job, EDITOR_BACKGROUND_MUSIC_GENERATION_JOB_KIND, EDITOR_ICON_SPRITESHEET_GENERATION_JOB_KIND, EDITOR_IMAGE_EDIT_JOB_KIND, EDITOR_IMAGE_GENERATION_JOB_KIND, EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND, EDITOR_VIDEO_GENERATION_JOB_KIND, @@ -845,21 +844,15 @@ pub async fn confirm_editor_agent_tool_call( AppError::from_status(axum::http::StatusCode::INTERNAL_SERVER_ERROR) .with_details(json!({"message": format!("failed to serialize tool payload: {error}")})) })?; - let (job_id, dedupe_key) = editor_agent_tool_job_identity( - conversation.conversation_id.as_str(), - message_id, - tool_name.as_str(), - ); - let job = enqueue_editor_generation_job_with_identity( + let job = enqueue_editor_generation_job( &state, + &request_context, conversation.owner_user_id.as_str(), job_kind, conversation.project_id.clone(), request_label, u64::from(price_mud_points), &payload, - job_id, - dedupe_key, ) .await?; let message = &mut document.messages[message_id]; @@ -881,16 +874,6 @@ fn parse_confirm_tool_args(value: &Value) -> Res .map_err(|error| editor_agent_bad_request(format!("invalid tool call args: {error}"))) } -fn editor_agent_tool_job_identity( - conversation_id: &str, - message_id: usize, - tool_name: &str, -) -> (String, String) { - let dedupe_key = format!("editor-agent:{conversation_id}:{message_id}:{tool_name}"); - let digest = Sha256::digest(dedupe_key.as_bytes()); - (format!("task-editor-agent-{digest:x}"), dedupe_key) -} - async fn load_editor_agent_project( state: &AppState, conversation: &EditorAgentConversationRecord, diff --git a/server-rs/crates/api-server/src/editor_generation_queue.rs b/server-rs/crates/api-server/src/editor_generation_queue.rs index 640aa6dc9..e58ea8dc9 100644 --- a/server-rs/crates/api-server/src/editor_generation_queue.rs +++ b/server-rs/crates/api-server/src/editor_generation_queue.rs @@ -47,41 +47,12 @@ where T: Serialize, { let job_id = build_prefixed_uuid_id("task-"); - enqueue_editor_generation_job_with_identity( - state, - owner_user_id, - job_kind, - source_entity_id, - request_label, - price_mud_points, - payload, - job_id.clone(), - format!("editor-canvas:{job_kind}:{job_id}"), - ) - .await -} - -#[allow(clippy::too_many_arguments)] -pub(crate) async fn enqueue_editor_generation_job_with_identity( - state: &AppState, - owner_user_id: &str, - job_kind: &str, - source_entity_id: impl Into, - request_label: impl Into, - price_mud_points: u64, - payload: &T, - job_id: String, - dedupe_key: String, -) -> Result -where - T: Serialize, -{ let request_payload_json = serialize_editor_generation_job_payload(payload)?; let now_micros = current_utc_micros(); state .spacetime_client() .enqueue_external_generation_job(ExternalGenerationJobEnqueueRecordInput { - dedupe_key, + dedupe_key: format!("editor-canvas:{job_kind}:{job_id}"), job_id, job_kind: job_kind.to_string(), owner_user_id: owner_user_id.to_string(), 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 316e38ae4..48327dfa7 100644 --- a/server-rs/crates/api-server/src/external_generation_worker.rs +++ b/server-rs/crates/api-server/src/external_generation_worker.rs @@ -675,9 +675,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(error) => { let message = error.body_text(); fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -705,9 +703,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(error) => { let message = error.body_text(); fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -736,9 +732,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(error) => { let message = error.body_text(); fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -839,9 +833,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(response) => { let message = response_error_message(response).await; fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -870,9 +862,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(response) => { let message = response_error_message(response).await; fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -901,9 +891,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(response) => { let message = response_error_message(response).await; fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -932,9 +920,7 @@ async fn process_external_generation_job_once( ) .await { - Ok(result) => { - complete_editor_generation_job(&state, &worker_id, &job, result.0).await - } + Ok(_) => complete_editor_generation_job(&state, &worker_id, &job).await, Err(response) => { let message = response_error_message(response).await; fail_job(&state, &worker_id, &job, message.clone()).await?; @@ -1039,9 +1025,7 @@ async fn complete_editor_generation_job( state: &AppState, worker_id: &str, job: &ExternalGenerationJobRecord, - result: serde_json::Value, ) -> Result<(), String> { - let result = compact_editor_generation_result(result); complete_job( state, worker_id, @@ -1050,7 +1034,6 @@ async fn complete_editor_generation_job( json!({ "sourceModule": job.source_module.clone(), "sourceEntityId": job.source_entity_id.clone(), - "response": result, }) .to_string(), ), @@ -1058,26 +1041,6 @@ async fn complete_editor_generation_job( .await } -fn compact_editor_generation_result(mut result: serde_json::Value) -> serde_json::Value { - let Some(object) = result.as_object_mut() else { - return result; - }; - object.remove("project"); - object.remove("asset"); - object.remove("spritesheetAsset"); - for field in ["resource", "spritesheetResource"] { - let Some(resource) = object - .get_mut(field) - .and_then(serde_json::Value::as_object_mut) - else { - continue; - }; - resource - .retain(|key, _| matches!(key.as_str(), "resourceId" | "objectKey" | "assetObjectId")); - } - result -} - async fn complete_editor_generation_job_with_response( state: &AppState, worker_id: &str, @@ -1097,14 +1060,11 @@ 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) = warning + if let Some(warning) = extract_editor_generation_slice_warning(response) && let Some(object) = payload.as_object_mut() { object.insert("warning".to_string(), warning); @@ -1112,30 +1072,6 @@ 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")?; @@ -1398,16 +1334,7 @@ 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": "/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" - }, + "spritesheetImageSrc": "data:image/png;base64,SHOULD_NOT_PERSIST", "iconImageSrcs": [{"imageSrc": "data:image/png;base64,SHOULD_NOT_PERSIST"}], "sliceWarning": { "code": "insufficient-connected-components", @@ -1421,20 +1348,6 @@ 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!({ @@ -1442,7 +1355,8 @@ mod tests { "reason": "连通域数量不足" }) ); - assert!(!payload.to_string().contains("data:image")); + assert!(payload.get("spritesheetImageSrc").is_none()); + assert!(payload.get("iconImageSrcs").is_none()); } #[test]