回退外部生成任务分支改动
恢复外部生成 worker 的 master 行为 恢复画布生成任务默认入队标识 移除 Agent 自定义任务标识入口
This commit is contained in:
@@ -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<T: serde::de::DeserializeOwned>(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,
|
||||
|
||||
@@ -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<T>(
|
||||
state: &AppState,
|
||||
owner_user_id: &str,
|
||||
job_kind: &str,
|
||||
source_entity_id: impl Into<String>,
|
||||
request_label: impl Into<String>,
|
||||
price_mud_points: u64,
|
||||
payload: &T,
|
||||
job_id: String,
|
||||
dedupe_key: String,
|
||||
) -> Result<ExternalGenerationJobRecord, AppError>
|
||||
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(),
|
||||
|
||||
@@ -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<Value> {
|
||||
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]
|
||||
|
||||
Reference in New Issue
Block a user