roder-tools 0.1.0

Agentic software development tools and SDKs for Roder.
Documentation
use roder_api::tools::ToolExecutionContext;

pub(crate) fn shell_for_context(ctx: &ToolExecutionContext, fallback: &str) -> String {
    ctx.command_shell
        .as_deref()
        .and_then(roder_api::command_shell::normalize_command_shell)
        .unwrap_or_else(|| fallback.to_string())
}

pub(crate) fn command_args_for_shell(shell: &str, command: &str, login: bool) -> Vec<String> {
    if is_powershell(shell) {
        let mut args = vec!["-NoProfile".to_string()];
        if cfg!(windows) {
            args.extend(["-ExecutionPolicy".to_string(), "Bypass".to_string()]);
        }
        args.extend(["-Command".to_string(), command.to_string()]);
        return args;
    }

    vec![
        if login { "-lc" } else { "-c" }.to_string(),
        command.to_string(),
    ]
}

fn is_powershell(shell: &str) -> bool {
    let name = shell
        .rsplit(['/', '\\'])
        .next()
        .unwrap_or(shell)
        .trim()
        .trim_end_matches(".exe")
        .to_ascii_lowercase();
    matches!(name.as_str(), "powershell" | "pwsh")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn powershell_uses_command_argument_instead_of_unix_shell_flags() {
        let args = command_args_for_shell("powershell", "pnpm test", true);

        assert!(args.contains(&"-Command".to_string()));
        assert!(args.contains(&"pnpm test".to_string()));
        assert!(!args.contains(&"-lc".to_string()));
        assert!(!args.contains(&"-c".to_string()));
    }

    #[test]
    fn pwsh_path_is_detected_as_powershell() {
        let args = command_args_for_shell(r"C:\Program Files\PowerShell\7\pwsh.exe", "dir", false);

        assert!(args.contains(&"-Command".to_string()));
        assert!(!args.contains(&"-c".to_string()));
    }

    #[test]
    fn unix_shells_keep_login_and_non_login_flags() {
        assert_eq!(
            command_args_for_shell("bash", "printf ok", true),
            vec!["-lc".to_string(), "printf ok".to_string()]
        );
        assert_eq!(
            command_args_for_shell("/bin/sh", "printf ok", false),
            vec!["-c".to_string(), "printf ok".to_string()]
        );
    }
}