| 14 | #[async_trait] |
| 15 | impl Command for AddCommand { |
| 16 | async fn execute(&self, ctx: &AppContext) -> Result<(), Box<dyn Error>> { |
| 17 | let args = &self.task_args; |
| 18 | let name = args.resolved_name(); |
| 19 | |
| 20 | let agents = args.parse_and_validate_agents()?; |
| 21 | let prompt = args.resolve_prompt()?; |
| 22 | let repo_root = args.resolve_repo_root()?; |
| 23 | |
| 24 | // Create tasks for each agent |
| 25 | let mut created_tasks = Vec::new(); |
| 26 | let mut first_task_instructions: Option<String> = None; |
| 27 | |
| 28 | for (idx, agent) in agents.iter().enumerate() { |
| 29 | let task = if idx == 0 { |
| 30 | // First task: create normally |
| 31 | let task = args |
| 32 | .configure_builder( |
| 33 | repo_root.clone(), |
| 34 | name.clone(), |
| 35 | Some(agent.clone()), |
| 36 | prompt.clone(), |
| 37 | ) |
| 38 | .parent_id(self.parent_id.clone()) |
| 39 | .build(ctx) |
| 40 | .await?; |
| 41 | |
| 42 | // Capture instructions for reuse if in edit mode |
| 43 | if args.edit { |
| 44 | first_task_instructions = Some( |
| 45 | crate::file_system::read_file(&PathBuf::from(&task.instructions_file)) |
| 46 | .await?, |
| 47 | ); |
| 48 | } |
| 49 | |
| 50 | task |
| 51 | } else { |
| 52 | // Subsequent tasks: reuse instructions if edit mode |
| 53 | let builder = args |
| 54 | .configure_builder( |
| 55 | repo_root.clone(), |
| 56 | name.clone(), |
| 57 | Some(agent.clone()), |
| 58 | if first_task_instructions.is_some() { |
| 59 | None |
| 60 | } else { |
| 61 | prompt.clone() |
| 62 | }, |
| 63 | ) |
| 64 | .parent_id(self.parent_id.clone()); |
| 65 | |
| 66 | if let Some(ref instructions_content) = first_task_instructions { |
| 67 | // Write instructions to temporary file for this task |
| 68 | let tasks_file = ctx.tsk_env().tasks_file(); |
| 69 | let data_dir = tasks_file |
| 70 | .parent() |
| 71 | .ok_or("Unable to determine data directory")?; |
| 72 | let temp_instructions = |
| 73 | data_dir.join(format!("temp_instructions_{}.md", nanoid::nanoid!(8))); |