fix: 审批流程 user_id 动态绑定 + email 降为 Low 风险
- current_user_id 从 'wechat_user' 改为动态共享变量 - listen_loop 中每条消息更新 current_user_id - 修复 Rust 2024 edition 的 ref/move 问题 - email 读操作降为 Low(无副作用,避免审批死锁) - 审批死锁根因:approval_flow 阻塞 listen_loop, receive_messages 无法被再次调用 后续需重构为异步审批模式(工具返回 pending,listen_loop 驱动确认)
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
收发邮件(IMAP)。
|
||||
|
||||
## Risk Level
|
||||
High
|
||||
Low
|
||||
|
||||
## Parameters
|
||||
```json
|
||||
|
||||
+18
-6
@@ -194,6 +194,9 @@ async fn cmd_listen(
|
||||
Arc::new(ApprovalManager::new(Some(Arc::new(db.pool().clone()))))
|
||||
});
|
||||
|
||||
// 共享的当前用户 ID(用于审批消息)
|
||||
let current_user_id = Arc::new(tokio::sync::Mutex::new(String::new()));
|
||||
|
||||
let conversation = if enable_llm {
|
||||
let sys_prompt = std::env::var("WEIXIN_LLM_SYSTEM_PROMPT")
|
||||
.unwrap_or_else(|_| DEFAULT_SYSTEM_PROMPT.to_string());
|
||||
@@ -293,12 +296,14 @@ async fn cmd_listen(
|
||||
})
|
||||
};
|
||||
|
||||
let executor_user_id = current_user_id.clone();
|
||||
let executor: ToolExecutor = Arc::new(move |name: &str, args_json: &str| {
|
||||
let reg = registry_opt.clone();
|
||||
let approval = approval.clone();
|
||||
let send = send_wechat.clone();
|
||||
let session = session.clone();
|
||||
let memory_store = memory_store.clone();
|
||||
let current_user = executor_user_id.clone();
|
||||
let n = name.to_string();
|
||||
let args = args_json.to_string();
|
||||
|
||||
@@ -314,9 +319,10 @@ async fn cmd_listen(
|
||||
"read_summaries" => return Ok(context::tools::read_summaries(&session).await),
|
||||
_ => {}
|
||||
}
|
||||
let user_id = current_user.lock().await.clone();
|
||||
if let Some(ref reg) = reg {
|
||||
let params: serde_json::Value = serde_json::from_str(&args).unwrap_or(serde_json::json!({}));
|
||||
let mut ctx = ExecutionContext::new("wechat_user");
|
||||
let mut ctx = ExecutionContext::new(&user_id);
|
||||
if let Some(a) = approval { ctx = ctx.with_approval(a); }
|
||||
ctx = ctx.with_wechat(send);
|
||||
let result = reg.execute(&n, params, &ctx).await;
|
||||
@@ -361,6 +367,8 @@ async fn cmd_listen(
|
||||
|
||||
let shutdown = async { tokio::signal::ctrl_c().await.expect("Ctrl+C 失败") };
|
||||
|
||||
let listen_user_id = current_user_id.clone();
|
||||
|
||||
tokio::select! {
|
||||
_ = shutdown => {
|
||||
info!("收到退出信号,注销监听器...");
|
||||
@@ -368,7 +376,7 @@ async fn cmd_listen(
|
||||
file_state.save_runtime(&client.get_updates_buf().await);
|
||||
info!("已退出");
|
||||
}
|
||||
_ = listen_loop(&client, enable_llm, echo, &account_id, database, file_state, conversation, approval_manager) => {}
|
||||
_ = listen_loop(&client, enable_llm, echo, &account_id, database, file_state, conversation, approval_manager, listen_user_id) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,6 +389,7 @@ async fn listen_loop(
|
||||
file_state: &state::StateManager,
|
||||
conversation: Option<Conversation>,
|
||||
approval_manager: Option<Arc<ApprovalManager>>,
|
||||
current_user_id: Arc<tokio::sync::Mutex<String>>,
|
||||
) {
|
||||
loop {
|
||||
match client.receive_messages().await {
|
||||
@@ -441,21 +450,24 @@ async fn listen_loop(
|
||||
}
|
||||
}
|
||||
|
||||
// 审批回复检查:是否匹配待审批的确认码
|
||||
let is_approval_reply = if let Some(ref mgr) = approval_manager {
|
||||
// 审批回复检查
|
||||
let is_approval_reply = if let Some(mgr) = &approval_manager {
|
||||
mgr.handle_reply(from, text).await.is_some()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if is_approval_reply {
|
||||
info!("消息匹配审批确认码,不传给 LLM(已由审批系统处理)");
|
||||
info!("消息匹配审批确认码,不传给 LLM");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 更新当前用户(审批流程需要)
|
||||
*current_user_id.lock().await = from.to_string();
|
||||
|
||||
// LLM 回复
|
||||
if enable_llm {
|
||||
if let Some(ref conv) = conversation {
|
||||
if let Some(conv) = &conversation {
|
||||
let reply_result = if conv.spec().tools.is_some() {
|
||||
generate_reply_with_tools(conv, text.to_string(), database).await
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user