intent_engine/cli_handlers/
task.rs1use 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 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 match format.as_str() {
135 "json" => {
136 println!("{}", serde_json::to_string_pretty(&response)?);
137 },
138 _ => {
139 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 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 print_task_context(&context)?;
205 },
206 }
207
208 Ok(())
209}