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 {
96            status,
97            parent,
98            sort_by,
99            limit,
100            offset,
101        } => {
102            let ctx = ProjectContext::load().await?;
103            let task_mgr = TaskManager::new(&ctx.pool);
104
105            let parent_opt = parent.map(|p| {
106                if p == "null" {
107                    None
108                } else {
109                    p.parse::<i64>().ok()
110                }
111            });
112
113            // Parse sort_by parameter
114            use crate::db::models::TaskSortBy;
115            let sort_by_parsed = match sort_by.as_deref() {
116                Some("id") => Some(TaskSortBy::Id),
117                Some("priority") => Some(TaskSortBy::Priority),
118                Some("time") => Some(TaskSortBy::Time),
119                Some("focus") => Some(TaskSortBy::FocusAware),
120                None => None, // Use default from find_tasks
121                Some(other) => {
122                    return Err(IntentError::InvalidInput(format!(
123                        "Invalid sort_by value '{}'. Valid values: id, priority, time, focus",
124                        other
125                    )));
126                },
127            };
128
129            let result = task_mgr
130                .find_tasks(status.as_deref(), parent_opt, sort_by_parsed, limit, offset)
131                .await?;
132            println!("{}", serde_json::to_string_pretty(&result)?);
133        },
134
135        TaskCommands::Start { id, with_events } => {
136            let ctx = ProjectContext::load_or_init().await?;
137            let task_mgr = TaskManager::new(&ctx.pool);
138
139            let task = task_mgr.start_task(id, with_events).await?;
140            println!("{}", serde_json::to_string_pretty(&task)?);
141        },
142
143        TaskCommands::Done => {
144            let ctx = ProjectContext::load_or_init().await?;
145            let task_mgr = TaskManager::new(&ctx.pool);
146
147            let task = task_mgr.done_task().await?;
148            println!("{}", serde_json::to_string_pretty(&task)?);
149        },
150
151        TaskCommands::PickNext { format } => {
152            let ctx = ProjectContext::load_or_init().await?;
153            let task_mgr = TaskManager::new(&ctx.pool);
154
155            let response = task_mgr.pick_next().await?;
156
157            // Output based on format
158            match format.as_str() {
159                "json" => {
160                    println!("{}", serde_json::to_string_pretty(&response)?);
161                },
162                _ => {
163                    // Default to text format
164                    println!("{}", response.format_as_text());
165                },
166            }
167        },
168
169        TaskCommands::SpawnSubtask { name, spec_stdin } => {
170            let ctx = ProjectContext::load_or_init().await?;
171            let task_mgr = TaskManager::new(&ctx.pool);
172
173            let spec = if spec_stdin {
174                Some(read_stdin()?)
175            } else {
176                None
177            };
178
179            let subtask = task_mgr.spawn_subtask(&name, spec.as_deref()).await?;
180            println!("{}", serde_json::to_string_pretty(&subtask)?);
181        },
182
183        TaskCommands::DependsOn {
184            blocked_task_id,
185            blocking_task_id,
186        } => {
187            let ctx = ProjectContext::load().await?;
188
189            let dependency =
190                crate::dependencies::add_dependency(&ctx.pool, blocking_task_id, blocked_task_id)
191                    .await?;
192
193            let response = serde_json::json!({
194                "dependency_id": dependency.id,
195                "blocking_task_id": dependency.blocking_task_id,
196                "blocked_task_id": dependency.blocked_task_id,
197                "created_at": dependency.created_at,
198                "message": format!(
199                    "Dependency added: Task {} now depends on Task {}",
200                    blocked_task_id, blocking_task_id
201                )
202            });
203
204            println!("{}", serde_json::to_string_pretty(&response)?);
205        },
206
207        TaskCommands::Context { task_id } => {
208            let ctx = ProjectContext::load().await?;
209            let task_mgr = TaskManager::new(&ctx.pool);
210            let workspace_mgr = WorkspaceManager::new(&ctx.pool);
211
212            // If no task_id provided, use current task
213            let target_id = if let Some(id) = task_id {
214                id
215            } else {
216                let current = workspace_mgr.get_current_task().await?;
217                current.current_task_id.ok_or_else(|| {
218                    IntentError::InvalidInput(
219                        "No task currently focused. Use 'ie task start <ID>' or provide task_id"
220                            .to_string(),
221                    )
222                })?
223            };
224
225            let context = task_mgr.get_task_context(target_id).await?;
226
227            // Format and print the context
228            print_task_context(&context)?;
229        },
230    }
231
232    Ok(())
233}