task_graph_mcp/resources/
stats.rs1use crate::config::StatesConfig;
4use crate::db::Database;
5use anyhow::Result;
6use serde_json::{Value, json};
7
8pub fn get_stats_summary(db: &Database, states_config: &StatesConfig) -> Result<Value> {
9 let stats = db.get_stats(None, None, states_config)?;
10
11 Ok(json!({
12 "total_tasks": stats.total_tasks,
13 "by_status": stats.tasks_by_status,
14 "points": {
15 "total": stats.total_points,
16 "completed": stats.completed_points,
17 "remaining": stats.total_points - stats.completed_points
18 },
19 "time": {
20 "estimated_ms": stats.total_time_estimate_ms,
21 "actual_ms": stats.total_time_actual_ms
22 },
23 "cost_usd": stats.total_cost_usd,
24 "metrics": stats.total_metrics
25 }))
26}
27
28pub fn get_acp_plan(db: &Database) -> Result<Value> {
30 let tasks = db.get_all_tasks()?;
31 let deps = db.get_all_dependencies()?;
32
33 let mut blockers_map: std::collections::HashMap<String, Vec<String>> =
35 std::collections::HashMap::new();
36 for dep in &deps {
37 blockers_map
38 .entry(dep.to_task_id.to_string())
39 .or_default()
40 .push(dep.from_task_id.to_string());
41 }
42
43 let acp_tasks: Vec<Value> = tasks
45 .iter()
46 .map(|t| {
47 let blockers = blockers_map
48 .get(&t.id.to_string())
49 .cloned()
50 .unwrap_or_default();
51
52 let status = match t.status.as_str() {
54 "pending" => "todo",
55 "working" => "working",
56 "completed" => "done",
57 _ => &t.status, };
59
60 json!({
61 "id": t.id.to_string(),
62 "title": t.title,
63 "description": t.description,
64 "status": status,
65 "priority": t.priority,
66 "blockedBy": blockers,
67 "assignee": &t.worker_id,
68 "metadata": {
69 "points": t.points,
70 "timeEstimateMs": t.time_estimate_ms,
71 "timeActualMs": t.time_actual_ms,
72 "cost": {
73 "metrics": t.metrics,
74 "usd": t.cost_usd
75 }
76 }
77 })
78 })
79 .collect();
80
81 Ok(json!({
82 "version": "1.0",
83 "tasks": acp_tasks
84 }))
85}