新增: Phase3 EventBus Value载荷+桥接层
- EventBus 载荷改 serde_json::Value(D2 全19变体透传),删 AiBusEvent 强类型子集 - 新增 publish_event(AiChatEvent) helper(内部 to_value→publish,供 emit 双写) - 新增 remote_bridge.rs 桥接层(MiniCommand→Tauri command 路由+R1 同conv并发兜底) - agentic/mod.rs 11处 AiBusEvent→AiChatEvent 迁移(Error/Completed/Round)
This commit is contained in:
@@ -39,8 +39,6 @@ use df_storage::models::AiProviderRecord;
|
||||
|
||||
use crate::state::{AppState, LlmConcurrency};
|
||||
|
||||
use crate::commands::ai::event_bus::AiBusEvent;
|
||||
|
||||
use super::audit::process_tool_calls;
|
||||
use super::compress::compress_via_llm;
|
||||
use super::conversation::{save_conversation, TokenAccumulator};
|
||||
@@ -523,8 +521,9 @@ pub(crate) async fn run_agentic_loop(
|
||||
});
|
||||
// L3 emit 双写(2026-06-22):关键 AiError publish 到事件总线,供跨模块订阅。
|
||||
// EVENT_BUS_ENABLED 门控在 publish 内部(false 静默丢弃),无消费者时空转不报错。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Error {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiError {
|
||||
error: msg,
|
||||
error_type: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -541,8 +540,9 @@ pub(crate) async fn run_agentic_loop(
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
// L3 emit 双写:超时 AiError publish 到事件总线(同上,门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Error {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiError {
|
||||
error: err_msg,
|
||||
error_type: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -713,10 +713,11 @@ pub(crate) async fn run_agentic_loop(
|
||||
// generating 复位后再 emit Completed:保证前端收事件时后端已可接下一条(发送队列续发不被"正在生成中"拒绝)
|
||||
let _ = app_handle.emit("ai-chat-event", AiChatEvent::AiCompleted { total_tokens: usage.total_tokens, prompt_tokens: tokens.prompt(), completion_tokens: tokens.completion(), incomplete: None, conversation_id: Some(conv_id.clone()) });
|
||||
// L3 emit 双写:入口 stop 的 AiCompleted publish 到事件总线(EVENT_BUS_ENABLED 门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Completed {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiCompleted {
|
||||
total_tokens: usage.total_tokens,
|
||||
prompt_tokens: tokens.prompt(),
|
||||
completion_tokens: tokens.completion(),
|
||||
incomplete: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -806,7 +807,7 @@ pub(crate) async fn run_agentic_loop(
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
// L3 emit 双写:AiAgentRound publish 到事件总线(EVENT_BUS_ENABLED 门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Round {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiAgentRound {
|
||||
round: round_n,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
@@ -1174,8 +1175,9 @@ pub(crate) async fn run_agentic_loop(
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
// L3 emit 双写:Fatal AiError publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Error {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiError {
|
||||
error,
|
||||
error_type: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -1203,8 +1205,9 @@ pub(crate) async fn run_agentic_loop(
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
// L3 emit 双写:全 candidate 耗尽 AiError publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Error {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiError {
|
||||
error: err_msg,
|
||||
error_type: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -1262,10 +1265,11 @@ pub(crate) async fn run_agentic_loop(
|
||||
incomplete: Some(true),
|
||||
});
|
||||
// L3 emit 双写:MidStream 保文 AiCompleted publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Completed {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiCompleted {
|
||||
total_tokens: usage.total_tokens,
|
||||
prompt_tokens: tokens.prompt(),
|
||||
completion_tokens: tokens.completion(),
|
||||
incomplete: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -1329,10 +1333,11 @@ pub(crate) async fn run_agentic_loop(
|
||||
// generating 复位后再 emit Completed:保证前端收事件时后端已可接下一条(发送队列续发不被"正在生成中"拒绝)
|
||||
let _ = app_handle.emit("ai-chat-event", AiChatEvent::AiCompleted { total_tokens: usage.total_tokens, prompt_tokens: tokens.prompt(), completion_tokens: tokens.completion(), incomplete: None, conversation_id: Some(conv_id.clone()) });
|
||||
// L3 emit 双写:stream 后 stop 的 AiCompleted publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Completed {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiCompleted {
|
||||
total_tokens: usage.total_tokens,
|
||||
prompt_tokens: tokens.prompt(),
|
||||
completion_tokens: tokens.completion(),
|
||||
incomplete: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
return;
|
||||
@@ -1524,10 +1529,11 @@ pub(crate) async fn run_agentic_loop(
|
||||
let _ = app_handle.emit("ai-chat-event", AiChatEvent::AiCompleted { total_tokens: usage_total, prompt_tokens: tokens.prompt(), completion_tokens: tokens.completion(), incomplete: None, conversation_id: Some(conv_id.clone()) });
|
||||
// L3 emit 双写:正常完成 AiCompleted publish 到事件总线(EVENT_BUS_ENABLED 门控在 publish 内,
|
||||
// 无消费者空转留批3 真实消费者接入)。AiTextDelta/AiToolCall* 高频事件不双写(无消费者空转)。
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish(AiBusEvent::Completed {
|
||||
let _ = app_handle.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiCompleted {
|
||||
total_tokens: usage_total,
|
||||
prompt_tokens: tokens.prompt(),
|
||||
completion_tokens: tokens.completion(),
|
||||
incomplete: None,
|
||||
conversation_id: Some(conv_id.clone()),
|
||||
});
|
||||
}
|
||||
@@ -1654,8 +1660,9 @@ pub(crate) async fn try_continue_agent_loop(
|
||||
conversation_id: Some(conv_id.to_string()),
|
||||
});
|
||||
// L3 emit 双写:try_continue provider-Err AiError publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app.state::<AppState>().ai_event_bus.publish(AiBusEvent::Error {
|
||||
let _ = app.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiError {
|
||||
error: e,
|
||||
error_type: None,
|
||||
conversation_id: Some(conv_id.to_string()),
|
||||
});
|
||||
return;
|
||||
@@ -1723,7 +1730,7 @@ pub(crate) async fn try_continue_agent_loop(
|
||||
conversation_id: Some(conv_id_owned.clone()),
|
||||
});
|
||||
// L3 emit 双写:try_continue 续跑 AiAgentRound publish 到事件总线(门控在 publish 内)。
|
||||
let _ = app.state::<AppState>().ai_event_bus.publish(AiBusEvent::Round {
|
||||
let _ = app.state::<AppState>().ai_event_bus.publish_event(AiChatEvent::AiAgentRound {
|
||||
round: 0,
|
||||
conversation_id: Some(conv_id_owned.clone()),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user