intent_engine/cli_handlers/
task.rs

1use crate::cli::TaskCommands;
2use crate::cli_handlers::read_stdin;
3use crate::cli_handlers::utils::print_task_context;
4use crate::error::{IntentError, Result};
5use crate::project::ProjectContext;
6use crate::tasks::TaskManager;
7use crate::workspace::WorkspaceManager;
8
9pub async fn handle_task_command(cmd: TaskCommands) -> Result<()> {
10    match cmd {
11        TaskCommands::Add {
12            name,
13            parent,
14            spec_stdin,
15        } => {
16            let ctx = ProjectContext::load_or_init().await?;
17            let task_mgr = TaskManager::new(&ctx.pool);
18
19            let spec = if spec_stdin {
20                Some(read_stdin()?)
21            } else {
22                None
23            };
24
25            let task = task_mgr.add_task(&name, spec.as_deref(), parent).await?;
26            println!("{}", serde_json::to_string_pretty(&task)?);
27        },
28
29        TaskCommands::Get { id, with_events } => {
30            let ctx = ProjectContext::load().await?;
31            let task_mgr = TaskManager::new(&ctx.pool);
32
33            if with_events {
34                let task = task_mgr.get_task_with_events(id).await?;
35                println!("{}", serde_json::to_string_pretty(&task)?);
36            } else {
37                let task = task_mgr.get_task(id).await?;
38                println!("{}", serde_json::to_string_pretty(&task)?);
39            }
40        },
41
42        TaskCommands::Update {
43            id,
44            name,
45            parent,
46            status,
47            complexity,
48            priority,
49            spec_stdin,
50        } => {
51            let ctx = ProjectContext::load_or_init().await?;
52            let task_mgr = TaskManager::new(&ctx.pool);
53
54            let spec = if spec_stdin {
55                Some(read_stdin()?)
56            } else {
57                None
58            };
59
60            // Convert priority string to integer
61            let priority_int = match &priority {
62                Some(p) => Some(crate::priority::PriorityLevel::parse_to_int(p)?),
63                None => None,
64            };
65
66            let parent_opt = parent.map(Some);
67            let task = task_mgr
68                .update_task(
69                    id,
70                    name.as_deref(),
71                    spec.as_deref(),
72                    parent_opt,
73                    status.as_deref(),
74                    complexity,
75                    priority_int,
76                )
77                .await?;
78            println!("{}", serde_json::to_string_pretty(&task)?);
79        },
80
81        TaskCommands::Del { id } => {
82            let ctx = ProjectContext::load_or_init().await?;
83            let task_mgr = TaskManager::new(&ctx.pool);
84
85            task_mgr.delete_task(id).await?;
86            println!(
87                "{}",
88                serde_json::to_string_pretty(&serde_json::json!({
89                    "success": true,
90                    "message": format!("Task {} deleted", id)
91                }))?
92            );
93        },
94
95        TaskCommands::List { status, parent } => {
96            let ctx = ProjectContext::load().await?;
97            let task_mgr = TaskManager::new(&ctx.pool);
98
99            let parent_opt = parent.map(|p| {
100                if p == "null" {
101                    None
102                } else {
103                    p.parse::<i64>().ok()
104                }
105            });
106
107            let tasks = task_mgr.find_tasks(status.as_deref(), parent_opt).await?;
108            println!("{}", serde_json::to_string_pretty(&tasks)?);
109        },
110
111        TaskCommands::Start { id, with_events } => {
112            let ctx = ProjectContext::load_or_init().await?;
113            let task_mgr = TaskManager::new(&ctx.pool);
114
115            let task = task_mgr.start_task(id, with_events).await?;
116            println!("{}", serde_json::to_string_pretty(&task)?);
117        },
118
119        TaskCommands::Done => {
120            let ctx = ProjectContext::load_or_init().await?;
121            let task_mgr = TaskManager::new(&ctx.pool);
122
123            let task = task_mgr.done_task().await?;
124            println!("{}", serde_json::to_string_pretty(&task)?);
125        },
126
127        TaskCommands::PickNext { format } => {
128            let ctx = ProjectContext::load_or_init().await?;
129            let task_mgr = TaskManager::new(&ctx.pool);
130
131            let response = task_mgr.pick_next().await?;
132
133            // Output based on format
134            match format.as_str() {
135                "json" => {
136                    println!("{}", serde_json::to_string_pretty(&response)?);
137                },
138                _ => {
139                    // Default to text format
140                    println!("{}", response.format_as_text());
141                },
142            }
143        },
144
145        TaskCommands::SpawnSubtask { name, spec_stdin } => {
146            let ctx = ProjectContext::load_or_init().await?;
147            let task_mgr = TaskManager::new(&ctx.pool);
148
149            let spec = if spec_stdin {
150                Some(read_stdin()?)
151            } else {
152                None
153            };
154
155            let subtask = task_mgr.spawn_subtask(&name, spec.as_deref()).await?;
156            println!("{}", serde_json::to_string_pretty(&subtask)?);
157        },
158
159        TaskCommands::DependsOn {
160            blocked_task_id,
161            blocking_task_id,
162        } => {
163            let ctx = ProjectContext::load().await?;
164
165            let dependency =
166                crate::dependencies::add_dependency(&ctx.pool, blocking_task_id, blocked_task_id)
167                    .await?;
168
169            let response = serde_json::json!({
170                "dependency_id": dependency.id,
171                "blocking_task_id": dependency.blocking_task_id,
172                "blocked_task_id": dependency.blocked_task_id,
173                "created_at": dependency.created_at,
174                "message": format!(
175                    "Dependency added: Task {} now depends on Task {}",
176                    blocked_task_id, blocking_task_id
177                )
178            });
179
180            println!("{}", serde_json::to_string_pretty(&response)?);
181        },
182
183        TaskCommands::Context { task_id } => {
184            let ctx = ProjectContext::load().await?;
185            let task_mgr = TaskManager::new(&ctx.pool);
186            let workspace_mgr = WorkspaceManager::new(&ctx.pool);
187
188            // If no task_id provided, use current task
189            let target_id = if let Some(id) = task_id {
190                id
191            } else {
192                let current = workspace_mgr.get_current_task().await?;
193                current.current_task_id.ok_or_else(|| {
194                    IntentError::InvalidInput(
195                        "No task currently focused. Use 'ie task start <ID>' or provide task_id"
196                            .to_string(),
197                    )
198                })?
199            };
200
201            let context = task_mgr.get_task_context(target_id).await?;
202
203            // Format and print the context
204            print_task_context(&context)?;
205        },
206    }
207
208    Ok(())
209}