恢复编辑器 Agent 稳定任务标识
保留外部生成任务稳定 job id 与去重键 供异步结果查询按固定任务标识回填
This commit is contained in:
@@ -6,70 +6,71 @@ use module_editor_agent::framework::memory::VecMemory;
|
||||
use module_editor_agent::framework::run::PromptOutput;
|
||||
use module_editor_agent::framework::tool::Tool;
|
||||
use module_editor_agent::{
|
||||
derive_conversation_title, editor_agent_messages_object_key,
|
||||
EDITOR_AGENT_CONVERSATION_ID_PREFIX, EDITOR_AGENT_DEFAULT_CONVERSATION_TITLE,
|
||||
EDITOR_AGENT_CONVERSATION_ID_PREFIX, EDITOR_AGENT_DEFAULT_CONVERSATION_TITLE,
|
||||
derive_conversation_title, editor_agent_messages_object_key,
|
||||
};
|
||||
use platform_llm::LlmMessage;
|
||||
use serde::Serialize;
|
||||
use serde_json::{json, Value};
|
||||
use serde_json::{Value, json};
|
||||
use sha2::{Digest, Sha256};
|
||||
use shared_contracts::assets::{
|
||||
EditorBackgroundMusicGenerateRequest, EditorSoundEffectGenerateRequest,
|
||||
EditorVideoGenerateRequest,
|
||||
EditorBackgroundMusicGenerateRequest, EditorSoundEffectGenerateRequest,
|
||||
EditorVideoGenerateRequest,
|
||||
};
|
||||
use shared_contracts::editor_agent::{
|
||||
CreateEditorAgentConversationRequest, EditorAgentConversationListResponse,
|
||||
EditorAgentConversationMessagesDocument, EditorAgentConversationResponse,
|
||||
EditorAgentConversationSummary, EditorAgentMessage, EditorAgentMessageRequest,
|
||||
EditorAgentMessageResponse, EditorAgentMessageRole, EditorAgentToolCall,
|
||||
EditorAgentToolCallStatus,
|
||||
CreateEditorAgentConversationRequest, EditorAgentConversationListResponse,
|
||||
EditorAgentConversationMessagesDocument, EditorAgentConversationResponse,
|
||||
EditorAgentConversationSummary, EditorAgentMessage, EditorAgentMessageRequest,
|
||||
EditorAgentMessageResponse, EditorAgentMessageRole, EditorAgentToolCall,
|
||||
EditorAgentToolCallStatus,
|
||||
};
|
||||
use spacetime_client::{
|
||||
EditorAgentConversationCreateRecordInput, EditorAgentConversationDeleteRecordInput,
|
||||
EditorAgentConversationRecord, EditorAgentConversationTouchRecordInput,
|
||||
EditorProjectGetRecordInput,
|
||||
EditorAgentConversationCreateRecordInput, EditorAgentConversationDeleteRecordInput,
|
||||
EditorAgentConversationRecord, EditorAgentConversationTouchRecordInput,
|
||||
EditorProjectGetRecordInput,
|
||||
};
|
||||
|
||||
use crate::api_response::json_success_body;
|
||||
use crate::auth::AuthenticatedAccessToken;
|
||||
use module_editor_agent::agent::agent::LlmChatAgentBuilder;
|
||||
use crate::editor_agent::pricing::EditorAgentPricedTool;
|
||||
use module_editor_agent::agent::tools::edit_image::{EditImageTool, EditImageToolArgs};
|
||||
use module_editor_agent::agent::tools::generate_background_music::{
|
||||
GenerateBackgroundMusicTool, GenerateBackgroundMusicToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_character::GenerateCharacterTool;
|
||||
use module_editor_agent::agent::tools::generate_icon_spritesheet::{
|
||||
GenerateIconSpritesheetTool, GenerateIconSpritesheetToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_image::{GenerateImageTool, GenerateImageToolArgs};
|
||||
use module_editor_agent::agent::tools::generate_sound_effect::{
|
||||
GenerateSoundEffectTool, GenerateSoundEffectToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_ui_design::GenerateUiDesignTool;
|
||||
use module_editor_agent::agent::tools::generate_video::{GenerateVideoTool, GenerateVideoToolArgs};
|
||||
use crate::editor_agent::utils::{
|
||||
build_editor_agent_canvas_completion, conversation_detail_from_record, conversation_summary_from_record,
|
||||
editor_agent_bad_request, empty_messages_document, ensure_editor_project_access,
|
||||
normalize_editor_agent_attachments, now_rfc3339, read_messages_document,
|
||||
require_editor_agent_sidebar_enabled, write_messages_document, IntoImageId,
|
||||
IntoImageId, build_editor_agent_canvas_completion, conversation_detail_from_record,
|
||||
conversation_summary_from_record, editor_agent_bad_request, empty_messages_document,
|
||||
ensure_editor_project_access, normalize_editor_agent_attachments, now_rfc3339,
|
||||
read_messages_document, require_editor_agent_sidebar_enabled, write_messages_document,
|
||||
};
|
||||
use crate::editor_agent::{context, display_args, reconcile};
|
||||
use crate::editor_generation_config::EditorGenerationPricingConfig;
|
||||
use crate::editor_generation_queue::{
|
||||
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,
|
||||
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,
|
||||
enqueue_editor_generation_job_with_identity,
|
||||
};
|
||||
use crate::editor_project::{
|
||||
EditorIconSpritesheetGenerationRequest, EditorImageEditRequest, EditorImageGenerationRequest,
|
||||
EditorIconSpritesheetGenerationRequest, EditorImageEditRequest, EditorImageGenerationRequest,
|
||||
};
|
||||
use crate::editor_project::{current_utc_micros, map_editor_project_error};
|
||||
use crate::http_error::AppError;
|
||||
use crate::request_context::RequestContext;
|
||||
use crate::state::AppState;
|
||||
use shared_kernel::{build_prefixed_uuid_id, normalize_optional_string};
|
||||
use module_editor_agent::agent::agent::LlmChatAgentBuilder;
|
||||
use module_editor_agent::agent::tools::context::EditorToolContext;
|
||||
use module_editor_agent::agent::tools::edit_image::{EditImageTool, EditImageToolArgs};
|
||||
use module_editor_agent::agent::tools::generate_background_music::{
|
||||
GenerateBackgroundMusicTool, GenerateBackgroundMusicToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_character::GenerateCharacterTool;
|
||||
use module_editor_agent::agent::tools::generate_icon_spritesheet::{
|
||||
GenerateIconSpritesheetTool, GenerateIconSpritesheetToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_image::{GenerateImageTool, GenerateImageToolArgs};
|
||||
use module_editor_agent::agent::tools::generate_sound_effect::{
|
||||
GenerateSoundEffectTool, GenerateSoundEffectToolArgs,
|
||||
};
|
||||
use module_editor_agent::agent::tools::generate_ui_design::GenerateUiDesignTool;
|
||||
use module_editor_agent::agent::tools::generate_video::{GenerateVideoTool, GenerateVideoToolArgs};
|
||||
use shared_kernel::{build_prefixed_uuid_id, normalize_optional_string};
|
||||
|
||||
pub async fn editor_agent_message(
|
||||
State(state): State<AppState>,
|
||||
@@ -844,15 +845,21 @@ 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 = enqueue_editor_generation_job(
|
||||
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(
|
||||
&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];
|
||||
@@ -874,6 +881,16 @@ 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,12 +47,41 @@ 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: format!("editor-canvas:{job_kind}:{job_id}"),
|
||||
dedupe_key,
|
||||
job_id,
|
||||
job_kind: job_kind.to_string(),
|
||||
owner_user_id: owner_user_id.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user