use axum::response::sse::Event; use serde::Serialize; use serde_json::{Value, json}; use shared_contracts::creative_agent::{CreativeAgentErrorEvent, CreativeAgentSseEventType}; pub fn creative_sse_json_event(event: CreativeAgentSseEventType, payload: T) -> Event where T: Serialize, { let event_name = creative_event_name(event); match serde_json::to_value(payload) .ok() .and_then(|value| Event::default().event(event_name).json_data(value).ok()) { Some(event) => event, None => creative_sse_error_event(None, "SSE_SERIALIZE_FAILED", "SSE payload 序列化失败"), } } pub fn creative_sse_json_value_event(event_name: &str, payload: Value) -> Event { Event::default() .event(event_name) .json_data(payload) .unwrap_or_else(|_| { creative_sse_error_event(None, "SSE_SERIALIZE_FAILED", "SSE payload 序列化失败") }) } pub fn creative_sse_error_event( session_id: Option, code: impl Into, message: impl Into, ) -> Event { let payload = serde_json::to_string(&CreativeAgentErrorEvent { session_id, code: code.into(), message: message.into(), recoverable: false, }) .unwrap_or_else(|_| { json!({ "sessionId": null, "code": "SSE_ERROR_SERIALIZE_FAILED", "message": "SSE 错误事件序列化失败", "recoverable": false, }) .to_string() }); Event::default().event("error").data(payload) } fn creative_event_name(event: CreativeAgentSseEventType) -> &'static str { match event { CreativeAgentSseEventType::Stage => "stage", CreativeAgentSseEventType::AgentMessageDelta => "agent_message_delta", CreativeAgentSseEventType::ThoughtSummaryDelta => "thought_summary_delta", CreativeAgentSseEventType::PuzzleTemplateCatalog => "puzzle_template_catalog", CreativeAgentSseEventType::PuzzleTemplateSelection => "puzzle_template_selection", CreativeAgentSseEventType::PuzzleCostRange => "puzzle_cost_range", CreativeAgentSseEventType::PuzzleLevelPlan => "puzzle_level_plan", CreativeAgentSseEventType::ToolStarted => "tool_started", CreativeAgentSseEventType::ToolCompleted => "tool_completed", CreativeAgentSseEventType::Reflection => "reflection", CreativeAgentSseEventType::TargetSession => "target_session", CreativeAgentSseEventType::Session => "session", CreativeAgentSseEventType::Error => "error", CreativeAgentSseEventType::Done => "done", } }