| 321 | } |
| 322 | |
| 323 | fn handoff_codex_lifecycle(&self, input: &[u8]) -> CliResult<()> { |
| 324 | let exe = std::env::current_exe().map_err(|e| { |
| 325 | CliError::Internal(anyhow!("Failed to resolve atomic executable: {}", e)) |
| 326 | })?; |
| 327 | |
| 328 | let mut child = ProcessCommand::new(exe) |
| 329 | .arg("agent") |
| 330 | .arg("hooks") |
| 331 | .arg(&self.agent_name) |
| 332 | .arg(&self.verb) |
| 333 | .arg("--foreground") |
| 334 | .stdin(Stdio::piped()) |
| 335 | .stdout(Stdio::null()) |
| 336 | .stderr(Stdio::null()) |
| 337 | .spawn() |
| 338 | .map_err(|e| { |
| 339 | CliError::Internal(anyhow!( |
| 340 | "Failed to start background Codex {} worker: {}", |
| 341 | self.verb, |
| 342 | e, |
| 343 | )) |
| 344 | })?; |
| 345 | |
| 346 | if let Some(mut stdin) = child.stdin.take() { |
| 347 | stdin.write_all(input).map_err(|e| { |
| 348 | CliError::Io(std::io::Error::new( |
| 349 | e.kind(), |
| 350 | format!( |
| 351 | "Failed to pass Codex {} input to background worker: {}", |
| 352 | self.verb, e, |
| 353 | ), |
| 354 | )) |
| 355 | })?; |
| 356 | } |
| 357 | |
| 358 | Ok(()) |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | // Tests |