修复: 模型停用无效根因 + 上下文归位/压缩守卫
- 模型停用无效根因: get_active_provider 两条路径均不校验 enabled(显式活跃直返/默认只挑 is_default) → 收敛为启用集合解析,无启用 provider 明确报错 - 压缩/标题兜底模型不校验 enabled → 新增 resolve_fallback_model 纯函数(title 复用同一实现,单一源无双轨) - 上下文多夹层归位修复: gather_tool_responses 聚拢该头全部响应(此前第二个夹层之后的响应仍被判未闭合剥除) - 压缩后台任务加内容版本哨兵(取首条消息 id,否掉 len:压缩期间 loop 正常 append 会致守卫永不生效) + panic 兜底复位标志 - 902 超时类失败与其它 Fatal 区分停靠文案(点继续可续跑) - 子代理事件按 conv 改挂(route_scope) + 运行期事件推父会话视图 - 飞书 13a 真根因: run_stream_refresher 死代码(提前 drop)+静默钟被心跳重置 → 帧通道+仅内容事件重置 - 项目详情文件查看: F22 目录不存在误显非 Git 仓库 / F24 模块为仓库子目录时 git 徽标全失效(scope_git_path 按 show-prefix 剥前缀) - 更新徽章通道错配(Tauri 事件 vs window CustomEvent 同名不同通道,徽章此前永不触发) - ProjectCard 卡片根 keydown 顶替内嵌按钮(补 e.target 守卫) - i18n 坏键 ai.aiTool.rejectedHint → aiTool.rejectedHint(双缺会渲染裸 key) - miniapp 三处: 会话列表刷新漏网/看门狗节流致新一轮无兜底/newConversation 漏清看门狗
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
//! re-export 经 audit/mod.rs `pub(crate) use finalize::audit_finalize;` 保持
|
||||
//! `commands::ai::audit::*` 路径透明(调用方零变更)。
|
||||
|
||||
use crate::commands::ai::tool_result_offload;
|
||||
use crate::commands::now_millis;
|
||||
use crate::state::AppState;
|
||||
|
||||
@@ -12,7 +13,13 @@ use crate::state::AppState;
|
||||
/// 走专用 find_by_tool_call_id —— 通用 query 宏硬编码 ORDER BY created_at DESC,
|
||||
/// 而 ai_tool_executions 无该列,调用会报 "no such column: created_at" 被 unwrap_or_default 吞掉,
|
||||
/// 导致审批后审计记录永久卡 pending。
|
||||
pub(crate) async fn audit_finalize(state: &AppState, tool_call_id: &str, status: &str, result: Option<String>) {
|
||||
pub(crate) async fn audit_finalize(
|
||||
state: &AppState,
|
||||
tool_call_id: &str,
|
||||
status: &str,
|
||||
result: Option<String>,
|
||||
duration_ms: Option<i64>,
|
||||
) {
|
||||
// 区分 Err(DB 故障)与 Ok(None)(真无记录):原 unwrap_or_default 把 Err 压成 None,
|
||||
// DB 故障被「未找到」日志掩盖,审批后审计记录卡 pending 无确诊线索。
|
||||
let mut rec = match state.ai_tool_executions.find_by_tool_call_id(tool_call_id).await {
|
||||
@@ -29,8 +36,13 @@ pub(crate) async fn audit_finalize(state: &AppState, tool_call_id: &str, status:
|
||||
rec.status = status.to_string();
|
||||
rec.decided_by = Some("human".to_string());
|
||||
rec.executed_at = Some(now_millis());
|
||||
// V50 纯执行耗时:审批路径由调用方(ai_approve/ai_authorize_dir)在真执行窗口测量后传入,
|
||||
// 与「requested_at→executed_at」(含等待人工批准)解耦。拒绝/超时未执行传 None。
|
||||
rec.duration_ms = duration_ms;
|
||||
if let Some(r) = result {
|
||||
rec.result = Some(r);
|
||||
// 与 audit_tool_call 的写侧一致:超阈值结果外置落盘,DB 只留句柄,防审批路径大结果
|
||||
// 绕过外置直接内联落库(工具真正执行发生在审批通过之后,这条才是大结果主入口)。
|
||||
rec.result = Some(tool_result_offload::offload_result(tool_call_id, &rec.tool_name, &r));
|
||||
}
|
||||
if let Err(e) = state.ai_tool_executions.update_full(&rec).await {
|
||||
tracing::error!("audit_finalize: 回填 tool_call_id={} 审计状态失败: {}", tool_call_id, e);
|
||||
|
||||
Reference in New Issue
Block a user