magi-code 0.63.3

Repository-aware CLI coding agent for terminal work
Documentation
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 {
        return Err(usage_error(
            "subcommands cannot be combined with --tui; 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 {
        return Err(usage_error(
            "--dump-prompt cannot be combined with --tui; 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 {
        return Ok(());
    }
    if args.print {
        return Err(usage_error(
            "--tui cannot be combined with --print; use one mode per invocation",
        ));
    }
    if !args.prompt.is_empty() {
        return Err(usage_error(
            "--tui does not support trailing PROMPT arguments in the Phase 4 MVP; launch --tui and type the prompt in Mission Control",
        ));
    }
    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(
            "--tui requires both stdin and stdout to be TTYs; use classic mode or --print for pipes/non-interactive use",
        ));
    }
    Ok(())
}