fix(cli): preserve split prompt words from Windows shims (#1160)
This commit is contained in:
+43
-10
@@ -92,15 +92,14 @@ struct Cli {
|
||||
no_mouse_capture: bool,
|
||||
#[arg(long = "skip-onboarding")]
|
||||
skip_onboarding: bool,
|
||||
#[arg(
|
||||
short = 'p',
|
||||
long = "prompt",
|
||||
value_name = "PROMPT",
|
||||
conflicts_with = "prompt"
|
||||
)]
|
||||
#[arg(short = 'p', long = "prompt", value_name = "PROMPT")]
|
||||
prompt_flag: Option<String>,
|
||||
#[arg(value_name = "PROMPT")]
|
||||
prompt: Option<String>,
|
||||
#[arg(
|
||||
value_name = "PROMPT",
|
||||
trailing_var_arg = true,
|
||||
allow_hyphen_values = true
|
||||
)]
|
||||
prompt: Vec<String>,
|
||||
#[command(subcommand)]
|
||||
command: Option<Commands>,
|
||||
}
|
||||
@@ -513,7 +512,17 @@ fn run() -> Result<()> {
|
||||
None => {
|
||||
let resolved_runtime = resolve_runtime_for_dispatch(&mut store, &runtime_overrides);
|
||||
let mut forwarded = Vec::new();
|
||||
if let Some(prompt) = cli.prompt_flag.clone().or_else(|| cli.prompt.clone()) {
|
||||
let prompt = cli.prompt_flag.iter().chain(cli.prompt.iter()).fold(
|
||||
String::new(),
|
||||
|mut acc, part| {
|
||||
if !acc.is_empty() {
|
||||
acc.push(' ');
|
||||
}
|
||||
acc.push_str(part);
|
||||
acc
|
||||
},
|
||||
);
|
||||
if !prompt.is_empty() {
|
||||
forwarded.push("--prompt".to_string());
|
||||
forwarded.push(prompt);
|
||||
}
|
||||
@@ -2533,7 +2542,31 @@ mod tests {
|
||||
let cli = parse_ok(&["deepseek", "-p", "Reply with exactly OK."]);
|
||||
|
||||
assert_eq!(cli.prompt_flag.as_deref(), Some("Reply with exactly OK."));
|
||||
assert_eq!(cli.prompt, None);
|
||||
assert!(cli.prompt.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_split_top_level_prompt_words_for_windows_cmd_shims() {
|
||||
let cli = parse_ok(&["deepseek", "hello", "world"]);
|
||||
|
||||
assert_eq!(cli.prompt, vec!["hello", "world"]);
|
||||
assert!(cli.command.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prompt_flag_keeps_split_tail_words_for_windows_cmd_shims() {
|
||||
let cli = parse_ok(&["deepseek", "-p", "hello", "world"]);
|
||||
|
||||
assert_eq!(cli.prompt_flag.as_deref(), Some("hello"));
|
||||
assert_eq!(cli.prompt, vec!["world"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn known_subcommands_still_parse_before_prompt_tail() {
|
||||
let cli = parse_ok(&["deepseek", "doctor"]);
|
||||
|
||||
assert!(cli.prompt.is_empty());
|
||||
assert!(matches!(cli.command, Some(Commands::Doctor(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+47
-7
@@ -110,8 +110,8 @@ struct Cli {
|
||||
feature_toggles: FeatureToggles,
|
||||
|
||||
/// Send a one-shot prompt (non-interactive)
|
||||
#[arg(short, long)]
|
||||
prompt: Option<String>,
|
||||
#[arg(short, long, value_name = "PROMPT", num_args = 1..)]
|
||||
prompt: Vec<String>,
|
||||
|
||||
/// YOLO mode: enable agent tools + shell execution
|
||||
#[arg(long)]
|
||||
@@ -265,7 +265,13 @@ enum Commands {
|
||||
#[derive(Args, Debug, Clone)]
|
||||
struct ExecArgs {
|
||||
/// Prompt to send to the model
|
||||
prompt: String,
|
||||
#[arg(
|
||||
value_name = "PROMPT",
|
||||
required = true,
|
||||
trailing_var_arg = true,
|
||||
allow_hyphen_values = true
|
||||
)]
|
||||
prompt: Vec<String>,
|
||||
/// Override model for this run
|
||||
#[arg(long)]
|
||||
model: Option<String>,
|
||||
@@ -277,6 +283,10 @@ struct ExecArgs {
|
||||
json: bool,
|
||||
}
|
||||
|
||||
fn join_prompt_parts(parts: &[String]) -> String {
|
||||
parts.join(" ")
|
||||
}
|
||||
|
||||
#[derive(Args, Debug, Clone, Default)]
|
||||
struct SetupArgs {
|
||||
/// Initialize MCP configuration at the configured path
|
||||
@@ -654,6 +664,7 @@ async fn main() -> Result<()> {
|
||||
.model
|
||||
.or_else(|| config.default_text_model.clone())
|
||||
.unwrap_or_else(|| config.default_model());
|
||||
let prompt = join_prompt_parts(&args.prompt);
|
||||
if args.auto || cli.yolo {
|
||||
let workspace = cli.workspace.clone().unwrap_or_else(|| {
|
||||
std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
|
||||
@@ -666,7 +677,7 @@ async fn main() -> Result<()> {
|
||||
run_exec_agent(
|
||||
&config,
|
||||
&model,
|
||||
&args.prompt,
|
||||
&prompt,
|
||||
workspace,
|
||||
max_subagents,
|
||||
true,
|
||||
@@ -675,9 +686,9 @@ async fn main() -> Result<()> {
|
||||
)
|
||||
.await
|
||||
} else if args.json {
|
||||
run_one_shot_json(&config, &model, &args.prompt).await
|
||||
run_one_shot_json(&config, &model, &prompt).await
|
||||
} else {
|
||||
run_one_shot(&config, &model, &args.prompt).await
|
||||
run_one_shot(&config, &model, &prompt).await
|
||||
}
|
||||
}
|
||||
Commands::Review(args) => {
|
||||
@@ -765,7 +776,8 @@ async fn main() -> Result<()> {
|
||||
|
||||
// One-shot prompt mode
|
||||
let config = load_config_from_cli(&cli)?;
|
||||
if let Some(prompt) = cli.prompt {
|
||||
if !cli.prompt.is_empty() {
|
||||
let prompt = join_prompt_parts(&cli.prompt);
|
||||
let model = config.default_model();
|
||||
return run_one_shot(&config, &model, &prompt).await;
|
||||
}
|
||||
@@ -4567,6 +4579,34 @@ mod terminal_mode_tests {
|
||||
Cli::try_parse_from(args).expect("CLI args should parse")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prompt_flag_accepts_split_prompt_words_for_windows_cmd_shims() {
|
||||
let cli = parse_cli(&["deepseek", "-p", "hello", "world"]);
|
||||
|
||||
assert_eq!(cli.prompt, vec!["hello", "world"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_accepts_split_prompt_words_for_windows_cmd_shims() {
|
||||
let cli = parse_cli(&["deepseek", "exec", "hello", "world"]);
|
||||
let Some(Commands::Exec(args)) = cli.command else {
|
||||
panic!("expected exec command");
|
||||
};
|
||||
|
||||
assert_eq!(args.prompt, vec!["hello", "world"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_keeps_flags_before_split_prompt_words() {
|
||||
let cli = parse_cli(&["deepseek", "exec", "--json", "hello", "world"]);
|
||||
let Some(Commands::Exec(args)) = cli.command else {
|
||||
panic!("expected exec command");
|
||||
};
|
||||
|
||||
assert!(args.json);
|
||||
assert_eq!(args.prompt, vec!["hello", "world"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alternate_screen_defaults_on_in_auto_mode() {
|
||||
let cli = parse_cli(&["deepseek"]);
|
||||
|
||||
Reference in New Issue
Block a user