use super::{AppError, AppResult, CliArgs};
use std::io::{self, IsTerminal};
fn usage_error(message: impl Into<String>) -> AppError {
AppError::usage(anyhow::anyhow!(message.into()))
}
pub(super) fn validate_subcommand_launch(args: &CliArgs) -> AppResult<()> {
if args.print {
return Err(usage_error(
"subcommands cannot be combined with --print; use one mode per invocation",
));
}
if args.tui || args.tui_experimental {
return Err(usage_error(
"subcommands cannot be combined with --tui or --tui-experimental; use one mode per invocation",
));
}
if args.dump_prompt {
return Err(usage_error(
"subcommands cannot be combined with --dump-prompt; use one mode per invocation",
));
}
if args.continue_session {
return Err(usage_error(
"subcommands cannot be combined with --continue; diagnostics do not attach to sessions",
));
}
if args.resume.is_some() {
return Err(usage_error(
"subcommands cannot be combined with --resume; diagnostics do not attach to sessions",
));
}
if args.no_session {
return Err(usage_error(
"subcommands cannot be combined with --no-session; diagnostics never create sessions",
));
}
if args.provider.is_some() {
return Err(usage_error(
"subcommands cannot be combined with --provider; diagnostics do not use provider auth",
));
}
if args.model.is_some() {
return Err(usage_error(
"subcommands cannot be combined with --model; diagnostics do not use provider models",
));
}
if args.api_key.is_some() {
return Err(usage_error(
"subcommands cannot be combined with --api-key; diagnostics do not authenticate",
));
}
if !args.prompt.is_empty() {
return Err(usage_error(
"subcommands do not accept trailing PROMPT arguments",
));
}
Ok(())
}
pub(super) fn validate_session_launch(args: &CliArgs) -> AppResult<()> {
if args.no_session && (args.continue_session || args.resume.is_some()) {
return Err(usage_error(
"--no-session cannot be combined with --continue or --resume",
));
}
if args.continue_session && args.resume.is_some() {
return Err(usage_error(
"--continue cannot be combined with --resume; choose one session target",
));
}
Ok(())
}
pub(super) fn validate_dump_prompt_launch(args: &CliArgs) -> AppResult<()> {
if !args.dump_prompt {
return Ok(());
}
if args.provider.is_none() {
return Err(usage_error(
"--dump-prompt requires --provider with one of: anthropic, openai, openai-compatible, openai-codex, claude-code",
));
}
if args.print {
return Err(usage_error(
"--dump-prompt cannot be combined with --print; use one mode per invocation",
));
}
if args.tui || args.tui_experimental {
return Err(usage_error(
"--dump-prompt cannot be combined with --tui or --tui-experimental; use one mode per invocation",
));
}
if args.continue_session {
return Err(usage_error(
"--dump-prompt cannot be combined with --continue; dump mode never attaches to sessions",
));
}
if args.resume.is_some() {
return Err(usage_error(
"--dump-prompt cannot be combined with --resume; dump mode never attaches to sessions",
));
}
if args.no_session {
return Err(usage_error(
"--dump-prompt cannot be combined with --no-session; dump mode never creates sessions",
));
}
if args.model.is_some() {
return Err(usage_error(
"--dump-prompt cannot be combined with --model; provider schema target is selected by --provider",
));
}
if args.api_key.is_some() {
return Err(usage_error(
"--dump-prompt cannot be combined with --api-key; dump mode does not authenticate",
));
}
if !args.prompt.is_empty() {
return Err(usage_error(
"--dump-prompt does not accept trailing PROMPT arguments",
));
}
Ok(())
}
pub(super) fn validate_tui_launch(args: &CliArgs) -> AppResult<()> {
if !args.tui && !args.tui_experimental {
return Ok(());
}
if args.tui && args.tui_experimental {
return Err(usage_error(
"--tui and --tui-experimental cannot be combined; use one TUI mode per invocation",
));
}
let mode = if args.tui_experimental {
"--tui-experimental"
} else {
"--tui"
};
if args.print {
return Err(usage_error(format!(
"{mode} cannot be combined with --print; use one mode per invocation"
)));
}
if !args.prompt.is_empty() {
return Err(usage_error(format!(
"{mode} does not support trailing PROMPT arguments in the Phase 4 MVP; launch {mode} and type the prompt in Mission Control"
)));
}
if args.tui_experimental {
for (present, flag) in [
(args.provider.is_some(), "--provider"),
(args.model.is_some(), "--model"),
(args.api_key.is_some(), "--api-key"),
(args.continue_session, "--continue"),
(args.resume.is_some(), "--resume"),
(args.no_session, "--no-session"),
] {
if present {
return Err(usage_error(format!(
"{flag} is not supported with --tui-experimental; use --tui for agent execution"
)));
}
}
}
let stdin_is_tty = io::stdin().is_terminal();
let stdout_is_tty = io::stdout().is_terminal();
if !stdin_is_tty || !stdout_is_tty {
return Err(usage_error(format!(
"{mode} requires both stdin and stdout to be TTYs; use classic mode or --print for pipes/non-interactive use"
)));
}
Ok(())
}