@@ -901,34 +901,49 @@ pub async fn stream_custom_world_agent_message(
|
||||
if let Err(error) = draft_writer.ensure_started(state.spacetime_client()).await {
|
||||
tracing::warn!(error = %error, "自定义世界模板生成草稿任务启动失败,主生成流程继续执行");
|
||||
}
|
||||
let draft_sink = AiGenerationDraftSink::new(
|
||||
AiGenerationDraftContext::new(
|
||||
"custom_world",
|
||||
owner_user_id_for_stream.as_str(),
|
||||
session_id_for_stream.as_str(),
|
||||
operation_id.as_str(),
|
||||
"自定义世界模板生成草稿",
|
||||
),
|
||||
state.spacetime_client().clone(),
|
||||
);
|
||||
// 聊天回复必须等本轮模型解析、进度与会话快照全部落库后,
|
||||
// 再随最终 session 一次性返回,避免玩家先看到回复而进度仍停在旧状态。
|
||||
let turn_result = run_custom_world_agent_turn(
|
||||
CustomWorldAgentTurnRequest {
|
||||
llm_client: state.llm_client(),
|
||||
session: &session,
|
||||
quick_fill_requested,
|
||||
focus_card_id,
|
||||
},
|
||||
move |text| {
|
||||
draft_sink.persist_visible_text_async(text);
|
||||
},
|
||||
)
|
||||
.await;
|
||||
if let Ok(result) = &turn_result {
|
||||
let (reply_tx, mut reply_rx) = tokio::sync::mpsc::unbounded_channel::<String>();
|
||||
// Agent turn 仍负责完整 JSON 解析和最终写回;这里把 replyText 增量桥接成前端可见的 SSE 分片。
|
||||
let turn_result = {
|
||||
let run_turn = run_custom_world_agent_turn(
|
||||
CustomWorldAgentTurnRequest {
|
||||
llm_client: state.llm_client(),
|
||||
session: &session,
|
||||
quick_fill_requested,
|
||||
focus_card_id,
|
||||
},
|
||||
move |text| {
|
||||
let _ = reply_tx.send(text.to_string());
|
||||
},
|
||||
);
|
||||
tokio::pin!(run_turn);
|
||||
|
||||
loop {
|
||||
// 不等待最终 session 落库即可先推送回复进度;session/done 仍在 finalize 成功后发送。
|
||||
tokio::select! {
|
||||
result = &mut run_turn => break result,
|
||||
maybe_text = reply_rx.recv() => {
|
||||
if let Some(text) = maybe_text {
|
||||
draft_writer
|
||||
.persist_visible_text(state.spacetime_client(), text.as_str())
|
||||
.await;
|
||||
yield Ok::<Event, Infallible>(custom_world_sse_json_event_or_error(
|
||||
"reply_delta",
|
||||
json!({ "text": text }),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while let Some(text) = reply_rx.recv().await {
|
||||
draft_writer
|
||||
.persist_visible_text(state.spacetime_client(), result.assistant_reply_text.as_str())
|
||||
.persist_visible_text(state.spacetime_client(), text.as_str())
|
||||
.await;
|
||||
yield Ok::<Event, Infallible>(custom_world_sse_json_event_or_error(
|
||||
"reply_delta",
|
||||
json!({ "text": text }),
|
||||
));
|
||||
}
|
||||
|
||||
let finalize_input = match turn_result {
|
||||
|
||||
Reference in New Issue
Block a user