nils-codex-cli 0.7.3

CLI crate for nils-codex-cli in the nils-cli workspace.
Documentation
use nils_test_support::bin;
use nils_test_support::cmd::{self, CmdOutput};
use pretty_assertions::assert_eq;
use serde_json::Value;
use std::path::PathBuf;

fn codex_cli_bin() -> PathBuf {
    bin::resolve("codex-cli")
}

fn gemini_cli_bin() -> PathBuf {
    bin::resolve("gemini-cli")
}

fn run_codex(args: &[&str]) -> CmdOutput {
    let bin = codex_cli_bin();
    cmd::run(&bin, args, &[], None)
}

fn run_gemini(args: &[&str]) -> CmdOutput {
    let bin = gemini_cli_bin();
    cmd::run(&bin, args, &[], None)
}

fn extract_commands(help_text: &str) -> Vec<String> {
    let mut commands = Vec::new();
    let mut in_commands = false;

    for line in help_text.lines() {
        if line.trim() == "Commands:" {
            in_commands = true;
            continue;
        }
        if !in_commands {
            continue;
        }
        if line.trim().is_empty() {
            break;
        }

        let trimmed = line.trim_start();
        if trimmed.starts_with('-') {
            continue;
        }

        if let Some(command) = trimmed.split_whitespace().next() {
            commands.push(command.to_string());
        }
    }

    commands
}

#[test]
fn parity_oracle_topology_matches_gemini() {
    let codex = run_codex(&["--help"]);
    let gemini = run_gemini(&["--help"]);
    assert_eq!(codex.code, 0, "stderr={}", codex.stderr_text());
    assert_eq!(gemini.code, 0, "stderr={}", gemini.stderr_text());

    let codex_commands = extract_commands(&codex.stdout_text());
    let gemini_commands = extract_commands(&gemini.stdout_text());
    assert_eq!(codex_commands, gemini_commands);
}

#[test]
fn parity_oracle_json_flags_match_gemini_for_auth_and_diag_help() {
    let codex_auth = run_codex(&["auth", "current", "--help"]);
    let gemini_auth = run_gemini(&["auth", "current", "--help"]);
    assert_eq!(codex_auth.code, 0);
    assert_eq!(gemini_auth.code, 0);
    let codex_auth_text = codex_auth.stdout_text();
    let gemini_auth_text = gemini_auth.stdout_text();
    for token in ["--format", "--json"] {
        assert!(codex_auth_text.contains(token));
        assert!(gemini_auth_text.contains(token));
    }

    let codex_diag = run_codex(&["diag", "rate-limits", "--help"]);
    let gemini_diag = run_gemini(&["diag", "rate-limits", "--help"]);
    assert_eq!(codex_diag.code, 0);
    assert_eq!(gemini_diag.code, 0);
    let codex_diag_text = codex_diag.stdout_text();
    let gemini_diag_text = gemini_diag.stdout_text();
    for token in ["--format", "--json", "--cached", "--async"] {
        assert!(codex_diag_text.contains(token));
        assert!(gemini_diag_text.contains(token));
    }
}

#[test]
fn parity_oracle_auth_json_schema_ids_are_provider_specific() {
    let codex = run_codex(&["auth", "current", "--json"]);
    let gemini = run_gemini(&["auth", "current", "--json"]);

    let codex_json: Value = serde_json::from_str(&codex.stdout_text()).expect("codex auth json");
    let gemini_json: Value = serde_json::from_str(&gemini.stdout_text()).expect("gemini auth json");

    assert_eq!(codex_json["command"], "auth current");
    assert_eq!(gemini_json["command"], "auth current");
    assert_eq!(codex_json["schema_version"], "codex-cli.auth.v1");
    assert_eq!(gemini_json["schema_version"], "gemini-cli.auth.v1");
}