重构: AI聊天可靠性批次(审批累计计数/write_file diff预览/会话隔离补清/token缓存)

This commit is contained in:
2026-06-16 19:56:29 +08:00
parent ba7f35552b
commit d00b30f0ba
12 changed files with 238 additions and 45 deletions

View File

@@ -51,6 +51,8 @@ pub async fn ai_regenerate(
session.generating = true;
session.stop_flag.store(false, Ordering::SeqCst);
session.agent_language = language.clone();
// F-260616-11: 重生成 = 新生命周期起点,iteration 从头计数。
session.iteration_used = 0;
let popped = session.messages.pop_last_assistant_round();
if !popped {
// 历史末尾无 AI 回复可弹(空对话/末尾是 user 错误态等),复位 generating 报错
@@ -105,7 +107,7 @@ pub async fn ai_regenerate(
let max_retries = state.agent_max_retries.load(Ordering::SeqCst);
tauri::async_runtime::spawn(async move {
run_agentic_loop(session_arc, tools_arc, db, app_handle, provider_config, system_prompt, conv_id, knowledge_config, llm_concurrency, max_iterations, max_retries).await;
run_agentic_loop(session_arc, tools_arc, db, app_handle, provider_config, system_prompt, conv_id, knowledge_config, llm_concurrency, max_iterations, max_retries, 0).await;
});
Ok("ok".to_string())
@@ -146,6 +148,8 @@ pub async fn ai_chat_send(
session.generating = true;
session.stop_flag.store(false, Ordering::SeqCst);
session.agent_language = language.clone();
// F-260616-11: 新对话生命周期 iteration 从头计数(累计计数器复位)。
session.iteration_used = 0;
session.messages.push(ChatMessage::user(&message));
// 首次发送时生成对话 id(懒创建:不立即落库,避免空对话残留;
@@ -201,7 +205,7 @@ pub async fn ai_chat_send(
let max_retries = state.agent_max_retries.load(Ordering::SeqCst);
tauri::async_runtime::spawn(async move {
run_agentic_loop(session_arc, tools_arc, db, app_handle, provider_config, system_prompt, conv_id, knowledge_config, llm_concurrency, max_iterations, max_retries).await;
run_agentic_loop(session_arc, tools_arc, db, app_handle, provider_config, system_prompt, conv_id, knowledge_config, llm_concurrency, max_iterations, max_retries, 0).await;
});
Ok("ok".to_string())
@@ -251,8 +255,11 @@ pub async fn ai_approve(
}
// 审计:拒绝(决策者=human
audit_finalize(&state, &tool_call_id, "rejected", None).await;
// F-260616-11 决策 a: 审批续跑 iteration 累计(不重置)——读 session.iteration_used 透传
// 作 start_iteration,防多次审批反复跑满 max_iterations 致 token 失控。
let start_iter = state.ai_session.lock().await.iteration_used;
// 所有待审批处理完毕后恢复 agentic 循环
try_continue_agent_loop(&app, &state).await;
try_continue_agent_loop(&app, &state, start_iter).await;
return Ok("rejected".to_string());
}
@@ -301,8 +308,11 @@ pub async fn ai_approve(
save_conversation(&state.ai_session, &state.db, cid, None, None).await;
}
// F-260616-11 决策 a: 审批续跑 iteration 累计(不重置)——读 session.iteration_used 透传
// 作 start_iteration,防多次审批反复跑满 max_iterations 致 token 失控。
let start_iter = state.ai_session.lock().await.iteration_used;
// 所有待审批处理完毕后恢复 agentic 循环(recovered 无 live loop,try_continue 因 generating=false 自然不续)
try_continue_agent_loop(&app, &state).await;
try_continue_agent_loop(&app, &state, start_iter).await;
Ok("executed".to_string())
}
@@ -398,6 +408,8 @@ pub async fn ai_chat_edit(
session.generating = true;
session.stop_flag.store(false, Ordering::SeqCst);
session.agent_language = language.clone();
// F-260616-11: 编辑重生成 = 新生命周期起点,iteration 从头计数。
session.iteration_used = 0;
}
let _tool_defs = state.ai_tools.tool_definitions();
@@ -453,6 +465,7 @@ pub async fn ai_chat_edit(
llm_concurrency,
max_iterations,
max_retries,
0,
)
.await;
});
@@ -560,8 +573,10 @@ pub async fn ai_chat_stop(state: State<'_, AppState>, app: AppHandle) -> Result<
///
/// 场景run_agentic_loop 达 max_iterations 未收敛 → emit AiMaxRoundsReached + 保持
/// generating=true 暂停。用户点继续调本命令 → 复位 stop_flag防上一轮残留致续跑入口即退出
/// → 调 try_continue_agent_loop 重新 spawn run_agentic_loopiteration 从 0 重计天然再跑
/// max_iterations 轮决策 a)。
/// → 调 try_continue_agent_loop 重新 spawn run_agentic_loopiteration 从 0 重计(天然再跑
/// max_iterations 轮,决策 a),F-260616-11 落地后:重置 session.iteration_used=0 + 传
/// start_iteration=0(达 max 续跑重计);审批续跑(ai_approve)则累计传 session.iteration_used,
/// 两路径区分见 run_agentic_loop 达 max 分支注释。
///
/// 校验复用 ai_approve 模式generating 必须为 true暂停态+ active_conversation_id 一致性
/// (防陈旧 loop 续跑污染新对话)。无硬上限防无限续(决策 b用户主动授权 = 同意烧 token
@@ -581,9 +596,12 @@ pub async fn ai_continue_loop(
}
// 复位停止信号:暂停态可能因上一轮 stop_flag 残留为 true续跑 loop 入口会立即退出走完成流程
session.stop_flag.store(false, Ordering::SeqCst);
// F-260616-11 决策 a: 达 max 续跑重计 iteration(F-260616-03 决策 a,用户点继续=授权重来)。
// 审批续跑(ai_approve)累计不重置见另路径;本路径 start_iteration 传 0,loop 从头计数。
session.iteration_used = 0;
}
// 复用审批恢复续 loop 入口(不重写 loop其内部 spawn run_agentic_loop
try_continue_agent_loop(&app, &state).await;
try_continue_agent_loop(&app, &state, 0).await;
Ok("ok".to_string())
}
@@ -836,6 +854,11 @@ pub async fn ai_conversation_create(
session.active_conv_created_at = Some(now);
session.messages.clear();
session.pending_approvals.clear();
// F-260616-09(A 路线):补漏清字段维持单例软隔离,解「新建会话上下文残留」。
// stop_flag 复位 false:上方生成中分支曾置 true 停旧 loop,不复位则新会话 loop
// 启动即见 stop_flag=true 异常退出;agent_language 清空防新会话沿用旧会话语言设置。
session.stop_flag.store(false, Ordering::SeqCst);
session.agent_language = None;
Ok(serde_json::json!({ "id": id }))
}