use anyhow::Result;
use rusqlite::{params, Connection};
pub(super) fn recent_decisions_condition() -> (&'static str, i64) {
("ts >= datetime('now', '-7 days')", 100)
}
pub(super) fn query_failed_patterns(conn: &Connection, min_count: u32) -> Result<String> {
let (recent_cond, recent_limit) = recent_decisions_condition();
let min_i64 = min_count as i64;
let mut stmt = conn.prepare(&format!(
"SELECT task_description, COUNT(*) as cnt,
SUM(CASE WHEN task_completed = 1 THEN 1 ELSE 0 END) as successes
FROM decisions
WHERE {} AND task_description IS NOT NULL
GROUP BY task_description
HAVING cnt >= ?1 AND CAST(successes AS REAL) / cnt < 0.5
ORDER BY cnt DESC LIMIT {}",
recent_cond, recent_limit
))?;
let rows: Vec<String> = stmt
.query_map(params![min_i64], |row| {
let desc: String = row.get(0)?;
let cnt: i64 = row.get(1)?;
let succ: i64 = row.get(2)?;
Ok(format!(
"- 模式: {} | 出现: {}次 | 成功: {}次 ({:.0}%)",
desc,
cnt,
succ,
if cnt > 0 {
succ as f64 / cnt as f64 * 100.0
} else {
0.0
}
))
})?
.filter_map(|r| r.ok())
.collect();
Ok(rows.join("\n"))
}
pub(super) fn query_failed_executions(conn: &Connection) -> Result<String> {
let (recent_cond, recent_limit) = recent_decisions_condition();
let mut stmt = conn.prepare(&format!(
"SELECT task_description, tools_detail, feedback
FROM decisions
WHERE {} AND (task_completed = 0 OR failed_tools > 0) AND task_description IS NOT NULL
ORDER BY ts DESC LIMIT {}",
recent_cond, recent_limit
))?;
let rows: Vec<String> = stmt
.query_map([], |row| {
let desc: Option<String> = row.get(0)?;
let tools: Option<String> = row.get(1)?;
let fb: Option<String> = row.get(2)?;
Ok(format!(
"- 任务: {} | 工具: {} | 反馈: {}",
desc.unwrap_or_default(),
tools.unwrap_or_default(),
fb.unwrap_or_default(),
))
})?
.filter_map(|r| r.ok())
.collect();
Ok(rows.join("\n"))
}
pub(super) fn query_repeated_patterns(
conn: &Connection,
min_count: u32,
) -> Result<(String, Vec<String>)> {
let (recent_cond, recent_limit) = recent_decisions_condition();
let min_i64 = min_count as i64;
let mut stmt = conn.prepare(&format!(
"SELECT task_description, COUNT(*) as cnt,
SUM(CASE WHEN task_completed = 1 THEN 1 ELSE 0 END) as successes
FROM decisions
WHERE {} AND task_description IS NOT NULL
GROUP BY task_description
HAVING cnt >= ?1 AND CAST(successes AS REAL) / cnt >= 0.8
ORDER BY cnt DESC LIMIT {}",
recent_cond, recent_limit
))?;
let mut display_rows: Vec<String> = Vec::new();
let mut task_descs: Vec<String> = Vec::new();
for row in stmt
.query_map(params![min_i64], |row| {
let desc: String = row.get(0)?;
let cnt: i64 = row.get(1)?;
let succ: i64 = row.get(2)?;
Ok((desc, cnt, succ))
})?
.filter_map(|r| r.ok())
{
let (desc, cnt, succ) = row;
display_rows.push(format!(
"- 模式: {} | 出现: {}次 | 成功: {}次 ({:.0}%)",
desc,
cnt,
succ,
succ as f64 / cnt as f64 * 100.0
));
task_descs.push(desc);
}
Ok((display_rows.join("\n"), task_descs))
}
pub(super) fn query_pattern_executions(
conn: &Connection,
task_descriptions: &[String],
) -> Result<String> {
if task_descriptions.is_empty() {
return Ok(String::new());
}
let placeholders = task_descriptions
.iter()
.enumerate()
.map(|(i, _)| format!("?{}", i + 1))
.collect::<Vec<_>>()
.join(", ");
let (recent_cond, recent_limit) = recent_decisions_condition();
let sql = format!(
"SELECT task_description, tools_detail, elapsed_ms
FROM decisions
WHERE {} AND task_completed = 1 AND task_description IN ({})
ORDER BY ts DESC LIMIT {}",
recent_cond, placeholders, recent_limit
);
let mut stmt = conn.prepare(&sql)?;
let rows: Vec<String> = stmt
.query_map(
rusqlite::params_from_iter(task_descriptions.iter()),
|row| {
let desc: String = row.get(0)?;
let tools: Option<String> = row.get(1)?;
let elapsed: i64 = row.get(2)?;
Ok(format!(
"- 任务: {} | 工具: {} | 耗时: {}ms",
desc,
tools.unwrap_or_else(|| "N/A".to_string()),
elapsed
))
},
)?
.filter_map(|r| r.ok())
.collect();
Ok(rows.join("\n"))
}
pub(super) fn query_skill_failures(conn: &Connection, skill_name: &str) -> Result<String> {
let tool_pattern = format!("%{}%", skill_name);
let mut stmt = conn.prepare(
"SELECT task_description, tools_detail, feedback
FROM decisions
WHERE failed_tools > 0 AND tools_detail LIKE ?1
ORDER BY ts DESC LIMIT 5",
)?;
let rows: Vec<String> = stmt
.query_map(params![tool_pattern], |row| {
let desc: Option<String> = row.get(0)?;
let tools: Option<String> = row.get(1)?;
let fb: Option<String> = row.get(2)?;
Ok(format!(
"- 任务: {} | 工具详情: {} | 反馈: {}",
desc.unwrap_or_default(),
tools.unwrap_or_default(),
fb.unwrap_or_default(),
))
})?
.filter_map(|r| r.ok())
.collect();
Ok(rows.join("\n"))
}