优化: AI治理与性能(tool_failure_stats失败率统计命令 + git status仓库级缓存治cmd闪烁N²) + 销账

This commit is contained in:
lxy
2026-08-09 21:35:02 +08:00
parent e099eff4cb
commit 5a92e6056c
6 changed files with 375 additions and 25 deletions
@@ -463,6 +463,55 @@ impl AiToolExecutionRepo {
.await
.map_err(storage_err)?
}
/// 按工具聚合执行统计(status 分布计数,AC-5 运行时失败率画像数据源)。
///
/// 单条 GROUP BY 取 `(tool_name, status, count)` 三元组;内存聚合与失败率口径
/// (failed_rate = failed / (completed + failed))在命令层完成(record.rs
/// `tool_failure_stats`),本层只负责取数,不掺展示逻辑。
/// `from`:可选时间下限(millis,`requested_at >= from`),None = 全量。
///
/// 与本表其他查询同理走专用 SELECT(通用 query 宏硬编码 ORDER BY created_at,
/// 本表无该列)。`requested_at` 存毫秒数字符串,`CAST AS INTEGER` 数值比较
/// (对齐 `cleanup_stale_pending` 同口径)。参数化绑定防注入。
pub async fn stats_by_tool(&self, from: Option<i64>) -> Result<Vec<(String, String, i64)>> {
let conn = self.conn.clone();
tokio::task::spawn_blocking(move || {
let guard = conn.blocking_lock();
// 条件分支仅差 WHERE + 参数,一条 GROUP BY 复用(match 分支互斥,stmt 借用安全)
let (sql, param): (&str, Option<i64>) = match from {
Some(f) => (
"SELECT tool_name, status, COUNT(*) FROM ai_tool_executions \
WHERE CAST(requested_at AS INTEGER) >= ?1 GROUP BY tool_name, status",
Some(f),
),
None => (
"SELECT tool_name, status, COUNT(*) FROM ai_tool_executions \
GROUP BY tool_name, status",
None,
),
};
let row_map = |row: &rusqlite::Row| {
Ok((
row.get::<_, String>(0)?,
row.get::<_, String>(1)?,
row.get::<_, i64>(2)?,
))
};
let mut stmt = guard.prepare(sql).map_err(storage_err)?;
let mut rows = match param {
Some(f) => stmt.query_map(params![f], row_map).map_err(storage_err)?,
None => stmt.query_map([], row_map).map_err(storage_err)?,
};
let mut out = Vec::new();
for r in &mut rows {
out.push(r.map_err(storage_err)?);
}
Ok(out)
})
.await
.map_err(storage_err)?
}
}
// AiConversationRepo 的整体更新已由 impl_repo! 宏统一生成的 update_full 提供。