|
2 | 2 | mod event_processor; |
3 | 3 |
|
4 | 4 | use std::io::IsTerminal; |
| 5 | +use std::io::Read; |
5 | 6 | use std::path::Path; |
6 | 7 | use std::path::PathBuf; |
7 | 8 | use std::sync::Arc; |
@@ -40,6 +41,41 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any |
40 | 41 | config_overrides, |
41 | 42 | } = cli; |
42 | 43 |
|
| 44 | + // Determine the prompt based on CLI arg and/or stdin. |
| 45 | + let prompt = match prompt { |
| 46 | + Some(p) if p != "-" => p, |
| 47 | + // Either `-` was passed or no positional arg. |
| 48 | + maybe_dash => { |
| 49 | + // When no arg (None) **and** stdin is a TTY, bail out early – unless the |
| 50 | + // user explicitly forced reading via `-`. |
| 51 | + let force_stdin = matches!(maybe_dash.as_deref(), Some("-")); |
| 52 | + |
| 53 | + if std::io::stdin().is_terminal() && !force_stdin { |
| 54 | + eprintln!( |
| 55 | + "No prompt provided. Either specify one as an argument or pipe the prompt into stdin." |
| 56 | + ); |
| 57 | + std::process::exit(1); |
| 58 | + } |
| 59 | + |
| 60 | + // Ensure the user knows we are waiting on stdin, as they may |
| 61 | + // have gotten into this state by mistake. If so, and they are not |
| 62 | + // writing to stdin, Codex will hang indefinitely, so this should |
| 63 | + // help them debug in that case. |
| 64 | + if !force_stdin { |
| 65 | + eprintln!("Reading prompt from stdin..."); |
| 66 | + } |
| 67 | + let mut buffer = String::new(); |
| 68 | + if let Err(e) = std::io::stdin().read_to_string(&mut buffer) { |
| 69 | + eprintln!("Failed to read prompt from stdin: {e}"); |
| 70 | + std::process::exit(1); |
| 71 | + } else if buffer.trim().is_empty() { |
| 72 | + eprintln!("No prompt provided via stdin."); |
| 73 | + std::process::exit(1); |
| 74 | + } |
| 75 | + buffer |
| 76 | + } |
| 77 | + }; |
| 78 | + |
43 | 79 | let (stdout_with_ansi, stderr_with_ansi) = match color { |
44 | 80 | cli::Color::Always => (true, true), |
45 | 81 | cli::Color::Never => (false, false), |
|
0 commit comments