persist error message in oss doc
This commit is contained in:
@@ -18,11 +18,11 @@ use shared_contracts::assets::{
|
||||
EditorVideoGenerateRequest,
|
||||
};
|
||||
use shared_contracts::editor_agent::{
|
||||
CreateEditorAgentConversationRequest, EditorAgentConversationListResponse,
|
||||
EditorAgentConversationMessagesDocument, EditorAgentConversationResponse,
|
||||
EditorAgentConversationSummary, EditorAgentMessage, EditorAgentMessageRequest,
|
||||
EditorAgentMessageResponse, EditorAgentMessageRole, EditorAgentToolCall,
|
||||
EditorAgentToolCallStatus,
|
||||
CreateEditorAgentConversationRequest, EDITOR_AGENT_ERROR_MESSAGE_PREFIX,
|
||||
EditorAgentConversationListResponse, EditorAgentConversationMessagesDocument,
|
||||
EditorAgentConversationResponse, EditorAgentConversationSummary, EditorAgentMessage,
|
||||
EditorAgentMessageRequest, EditorAgentMessageResponse, EditorAgentMessageRole,
|
||||
EditorAgentToolCall, EditorAgentToolCallStatus,
|
||||
};
|
||||
use spacetime_client::{
|
||||
EditorAgentConversationCreateRecordInput, EditorAgentConversationDeleteRecordInput,
|
||||
@@ -210,17 +210,30 @@ pub async fn editor_agent_message(
|
||||
let tool_context = context::build_tool_context(&document);
|
||||
|
||||
// Build and run agent
|
||||
let llm_client = state.creative_agent_gpt5_client().ok_or_else(|| {
|
||||
AppError::from_status(axum::http::StatusCode::SERVICE_UNAVAILABLE)
|
||||
.with_details(json!({ "message": "Creative Agent GPT-5 client not configured" }))
|
||||
})?;
|
||||
let Some(llm_client) = state.creative_agent_gpt5_client() else {
|
||||
return persist_editor_agent_planning_error(
|
||||
&state,
|
||||
&conversation,
|
||||
&mut document,
|
||||
conversation_summary,
|
||||
"Creative Agent GPT-5 client not configured",
|
||||
)
|
||||
.await;
|
||||
};
|
||||
let llm_client = llm_client.clone();
|
||||
let pricing = state.editor_generation_pricing().await.map_err(|error| {
|
||||
AppError::from_status(axum::http::StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({
|
||||
"provider": "editor-generation-pricing",
|
||||
"message": error.to_string(),
|
||||
}))
|
||||
})?;
|
||||
let pricing = match state.editor_generation_pricing().await {
|
||||
Ok(pricing) => pricing,
|
||||
Err(error) => {
|
||||
return persist_editor_agent_planning_error(
|
||||
&state,
|
||||
&conversation,
|
||||
&mut document,
|
||||
conversation_summary,
|
||||
format!("failed to load editor generation pricing: {error}"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
|
||||
let memory = VecMemory::new(previous_messages);
|
||||
|
||||
@@ -265,11 +278,16 @@ pub async fn editor_agent_message(
|
||||
&tool_context,
|
||||
&pricing,
|
||||
) {
|
||||
Err(err) => Ok(Json(EditorAgentMessageResponse {
|
||||
conversation: conversation_summary,
|
||||
delta_messages: Vec::new(),
|
||||
error_message: Some(err.to_string()),
|
||||
})),
|
||||
Err(error) => {
|
||||
persist_editor_agent_planning_error(
|
||||
&state,
|
||||
&conversation,
|
||||
&mut document,
|
||||
conversation_summary,
|
||||
error.to_string(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
Ok(delta_messages) => {
|
||||
for msg in &delta_messages {
|
||||
document.messages.push(msg.clone());
|
||||
@@ -285,6 +303,39 @@ pub async fn editor_agent_message(
|
||||
}
|
||||
}
|
||||
|
||||
fn build_editor_agent_error_message(
|
||||
message_id: usize,
|
||||
error: impl std::fmt::Display,
|
||||
) -> EditorAgentMessage {
|
||||
EditorAgentMessage {
|
||||
id: message_id,
|
||||
client_message_id: None,
|
||||
role: EditorAgentMessageRole::System,
|
||||
text: format!("{EDITOR_AGENT_ERROR_MESSAGE_PREFIX}{error}"),
|
||||
attachments: Vec::new(),
|
||||
tool_call: None,
|
||||
created_at: now_rfc3339(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn persist_editor_agent_planning_error(
|
||||
state: &AppState,
|
||||
conversation: &EditorAgentConversationRecord,
|
||||
document: &mut EditorAgentConversationMessagesDocument,
|
||||
conversation_summary: EditorAgentConversationSummary,
|
||||
error: impl std::fmt::Display,
|
||||
) -> Result<Json<EditorAgentMessageResponse>, AppError> {
|
||||
let error_message = build_editor_agent_error_message(document.messages.len(), error);
|
||||
document.messages.push(error_message.clone());
|
||||
write_messages_document(state, conversation, document).await?;
|
||||
|
||||
Ok(Json(EditorAgentMessageResponse {
|
||||
conversation: conversation_summary,
|
||||
delta_messages: vec![error_message],
|
||||
error_message: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn validate_editor_agent_message_request(
|
||||
payload: &EditorAgentMessageRequest,
|
||||
) -> Result<String, AppError> {
|
||||
@@ -451,6 +502,16 @@ mod tests {
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_system_error_message_with_wire_prefix() {
|
||||
let message = build_editor_agent_error_message(3, "planning failed");
|
||||
|
||||
assert_eq!(message.id, 3);
|
||||
assert_eq!(message.role, EditorAgentMessageRole::System);
|
||||
assert_eq!(message.text, "ERROR planning failed");
|
||||
assert!(message.tool_call.is_none());
|
||||
}
|
||||
}
|
||||
fn editor_agent_system_prompt() -> &'static str {
|
||||
r#"
|
||||
|
||||
@@ -5,6 +5,7 @@ use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
pub const EDITOR_AGENT_MAX_ATTACHMENTS: usize = 9;
|
||||
pub const EDITOR_AGENT_ERROR_MESSAGE_PREFIX: &str = "ERROR ";
|
||||
pub const EDITOR_AGENT_TITLE_MAX_CHARS: usize = 20;
|
||||
pub const EDITOR_AGENT_DEFAULT_CONVERSATION_TITLE: &str = "新对话";
|
||||
pub const EDITOR_AGENT_MESSAGES_DOCUMENT_VERSION: u32 = 2;
|
||||
|
||||
Reference in New Issue
Block a user