1
This commit is contained in:
@@ -5,6 +5,7 @@ version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
async-stream = "0.3"
|
||||
axum = "0.8"
|
||||
base64 = "0.22"
|
||||
bytes = "1"
|
||||
|
||||
@@ -41,6 +41,9 @@ use std::convert::Infallible;
|
||||
|
||||
use crate::{
|
||||
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
|
||||
custom_world_agent_turn::{
|
||||
CustomWorldAgentTurnRequest, build_finalize_record_input, run_custom_world_agent_turn,
|
||||
},
|
||||
request_context::RequestContext, state::AppState,
|
||||
};
|
||||
|
||||
@@ -528,21 +531,56 @@ pub async fn submit_custom_world_agent_message(
|
||||
));
|
||||
}
|
||||
|
||||
let owner_user_id = authenticated.claims().user_id().to_string();
|
||||
let operation_id = build_prefixed_uuid_id("operation-");
|
||||
let submitted_at_micros = current_utc_micros();
|
||||
let operation = state
|
||||
.spacetime_client()
|
||||
.submit_custom_world_agent_message(CustomWorldAgentMessageSubmitRecordInput {
|
||||
session_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
session_id: session_id.clone(),
|
||||
owner_user_id: owner_user_id.clone(),
|
||||
user_message_id: client_message_id,
|
||||
user_message_text: message_text,
|
||||
operation_id: build_prefixed_uuid_id("operation-"),
|
||||
submitted_at_micros: current_utc_micros(),
|
||||
operation_id: operation_id.clone(),
|
||||
submitted_at_micros,
|
||||
})
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.get_custom_world_agent_session(session_id.clone(), owner_user_id.clone())
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
let turn_result = run_custom_world_agent_turn(
|
||||
CustomWorldAgentTurnRequest {
|
||||
llm_client: state.llm_client(),
|
||||
session: &session,
|
||||
quick_fill_requested: payload.quick_fill_requested.unwrap_or(false),
|
||||
focus_card_id: payload.focus_card_id.clone(),
|
||||
},
|
||||
|_| {},
|
||||
)
|
||||
.await;
|
||||
state
|
||||
.spacetime_client()
|
||||
.finalize_custom_world_agent_message(build_finalize_record_input(
|
||||
session_id,
|
||||
owner_user_id,
|
||||
operation_id,
|
||||
format!("assistant-{}", operation.operation_id),
|
||||
turn_result,
|
||||
current_utc_micros(),
|
||||
))
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
json!({
|
||||
@@ -591,7 +629,7 @@ pub async fn stream_custom_world_agent_message(
|
||||
}
|
||||
|
||||
let owner_user_id = authenticated.claims().user_id().to_string();
|
||||
state
|
||||
let operation = state
|
||||
.spacetime_client()
|
||||
.submit_custom_world_agent_message(CustomWorldAgentMessageSubmitRecordInput {
|
||||
session_id: session_id.clone(),
|
||||
@@ -607,31 +645,63 @@ pub async fn stream_custom_world_agent_message(
|
||||
})?;
|
||||
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.get_custom_world_agent_session(session_id.clone(), owner_user_id.clone())
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
let mut reply_updates = Vec::<String>::new();
|
||||
let turn_result = run_custom_world_agent_turn(
|
||||
CustomWorldAgentTurnRequest {
|
||||
llm_client: state.llm_client(),
|
||||
session: &session,
|
||||
quick_fill_requested: payload.quick_fill_requested.unwrap_or(false),
|
||||
focus_card_id: payload.focus_card_id.clone(),
|
||||
},
|
||||
|text| {
|
||||
reply_updates.push(text.to_string());
|
||||
},
|
||||
)
|
||||
.await;
|
||||
state
|
||||
.spacetime_client()
|
||||
.finalize_custom_world_agent_message(build_finalize_record_input(
|
||||
session_id.clone(),
|
||||
owner_user_id.clone(),
|
||||
operation.operation_id.clone(),
|
||||
format!("assistant-{}", operation.operation_id),
|
||||
turn_result,
|
||||
current_utc_micros(),
|
||||
))
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
let final_session = state
|
||||
.spacetime_client()
|
||||
.get_custom_world_agent_session(session_id, owner_user_id)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
custom_world_error_response(&request_context, map_custom_world_client_error(error))
|
||||
})?;
|
||||
let session_response = map_custom_world_agent_session_response(session);
|
||||
let reply_text = resolve_stream_reply_text(&session_response);
|
||||
let session_response = map_custom_world_agent_session_response(final_session);
|
||||
|
||||
// 这里仍保持“一次性返回完整事件序列”的兼容语义;
|
||||
// SSE 编码、标准响应头与 body frame 交给 Axum 内建实现维护。
|
||||
let events = vec![
|
||||
custom_world_sse_json_event("reply_delta", json!({ "text": reply_text }))
|
||||
.map_err(|error| custom_world_error_response(&request_context, error))?,
|
||||
let mut events = reply_updates
|
||||
.into_iter()
|
||||
.map(|text| custom_world_sse_json_event("reply_delta", json!({ "text": text })))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|error| custom_world_error_response(&request_context, error))?;
|
||||
events.push(
|
||||
custom_world_sse_json_event("session", json!({ "session": session_response }))
|
||||
.map_err(|error| custom_world_error_response(&request_context, error))?,
|
||||
);
|
||||
events.push(
|
||||
custom_world_sse_json_event("done", json!({ "ok": true }))
|
||||
.map_err(|error| custom_world_error_response(&request_context, error))?,
|
||||
];
|
||||
let stream = tokio_stream::iter(
|
||||
events
|
||||
.into_iter()
|
||||
.map(|event| Ok::<Event, Infallible>(event)),
|
||||
);
|
||||
|
||||
let stream = tokio_stream::iter(events.into_iter().map(|event| Ok::<Event, Infallible>(event)));
|
||||
Ok(Sse::new(stream).into_response())
|
||||
}
|
||||
|
||||
|
||||
2011
server-rs/crates/api-server/src/custom_world_agent_turn.rs
Normal file
2011
server-rs/crates/api-server/src/custom_world_agent_turn.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ mod character_animation_assets;
|
||||
mod character_visual_assets;
|
||||
mod config;
|
||||
mod custom_world;
|
||||
mod custom_world_agent_turn;
|
||||
mod custom_world_ai;
|
||||
mod error_middleware;
|
||||
mod health;
|
||||
|
||||
Reference in New Issue
Block a user