Codex Handbook
tools/src/tool_config_tests.rs 206 lines
use codex_features::Feature;use codex_features::Features;use codex_protocol::config_types::ModeKind;use codex_protocol::openai_models::ConfigShellToolType;use codex_protocol::openai_models::ModelInfo;use codex_protocol::openai_models::ModelVisibility;use codex_protocol::openai_models::TruncationPolicyConfig;use pretty_assertions::assert_eq;use super::*;fn model_with_shell_type(shell_type: ConfigShellToolType) -> ModelInfo {    ModelInfo {        slug: "test-model".to_string(),        display_name: "Test Model".to_string(),        description: None,        default_reasoning_level: None,        supported_reasoning_levels: Vec::new(),        shell_type,        visibility: ModelVisibility::List,        supported_in_api: true,        priority: 0,        additional_speed_tiers: Vec::new(),        service_tiers: Vec::new(),        default_service_tier: None,        availability_nux: None,        upgrade: None,        base_instructions: String::new(),        model_messages: None,        supports_reasoning_summaries: false,        default_reasoning_summary: Default::default(),        support_verbosity: false,        default_verbosity: None,        apply_patch_tool_type: None,        web_search_tool_type: Default::default(),        truncation_policy: TruncationPolicyConfig::tokens(/*limit*/ 1024),        supports_parallel_tool_calls: true,        supports_image_detail_original: false,        context_window: None,        max_context_window: None,        auto_compact_token_limit: None,        comp_hash: None,        effective_context_window_percent: 95,        experimental_supported_tools: Vec::new(),        input_modalities: codex_protocol::openai_models::default_input_modalities(),        used_fallback_model_metadata: false,        supports_search_tool: false,        use_responses_lite: false,        auto_review_model_override: None,        tool_mode: None,        multi_agent_version: None,    }}fn shell_features() -> Features {    let mut features = Features::with_defaults();    features.enable(Feature::ShellTool);    features.disable(Feature::ShellZshFork);    features.disable(Feature::UnifiedExec);    features.disable(Feature::UnifiedExecZshFork);    features}#[test]fn shell_type_is_derived_from_model_and_feature_gates() {    let model = model_with_shell_type(ConfigShellToolType::UnifiedExec);    let mut features = shell_features();    assert_eq!(        shell_type_for_model_and_features(&model, &features),        ConfigShellToolType::ShellCommand    );    features.enable(Feature::UnifiedExec);    let expected_unified_exec = if codex_utils_pty::conpty_supported() {        ConfigShellToolType::UnifiedExec    } else {        ConfigShellToolType::ShellCommand    };    assert_eq!(        shell_type_for_model_and_features(&model, &features),        expected_unified_exec    );    features.enable(Feature::ShellZshFork);    assert_eq!(        shell_type_for_model_and_features(&model, &features),        ConfigShellToolType::ShellCommand    );    features.enable(Feature::UnifiedExecZshFork);    assert_eq!(        shell_type_for_model_and_features(&model, &features),        expected_unified_exec    );    features.disable(Feature::ShellTool);    assert_eq!(        shell_type_for_model_and_features(&model, &features),        ConfigShellToolType::Disabled    );}#[test]fn shell_command_backend_requires_both_shell_tool_and_zsh_fork() {    let mut features = shell_features();    assert_eq!(        shell_command_backend_for_features(&features),        ShellCommandBackendConfig::Classic    );    features.enable(Feature::ShellZshFork);    assert_eq!(        shell_command_backend_for_features(&features),        ShellCommandBackendConfig::ZshFork    );    features.disable(Feature::ShellTool);    assert_eq!(        shell_command_backend_for_features(&features),        ShellCommandBackendConfig::Classic    );}#[test]fn unified_exec_feature_mode_follows_composition_dependencies() {    let mut features = shell_features();    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::Disabled    );    features.enable(Feature::UnifiedExec);    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::Direct    );    features.enable(Feature::UnifiedExecZshFork);    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::Direct    );    features.enable(Feature::ShellZshFork);    features.disable(Feature::UnifiedExecZshFork);    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::Disabled    );    features.enable(Feature::UnifiedExecZshFork);    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::ZshFork    );    features.disable(Feature::ShellTool);    assert_eq!(        unified_exec_feature_mode_for_features(&features),        UnifiedExecFeatureMode::Disabled    );}#[test]fn request_user_input_modes_follow_default_mode_feature() {    let mut features = Features::with_defaults();    features.disable(Feature::DefaultModeRequestUserInput);    assert_eq!(        request_user_input_available_modes(&features),        vec![ModeKind::Plan]    );    features.enable(Feature::DefaultModeRequestUserInput);    assert_eq!(        request_user_input_available_modes(&features),        vec![ModeKind::Default, ModeKind::Plan]    );}#[test]fn unified_exec_shell_mode_uses_zsh_fork_only_when_all_inputs_match() {    let exe = std::env::current_exe().expect("current exe path");    let shell = exe.clone();    let mode = UnifiedExecShellMode::for_session(        UnifiedExecFeatureMode::ZshFork,        ToolUserShellType::Zsh,        Some(&shell),        Some(&exe),    );    if cfg!(unix) {        assert!(matches!(mode, UnifiedExecShellMode::ZshFork(_)));    } else {        assert_eq!(mode, UnifiedExecShellMode::Direct);    }    assert_eq!(        UnifiedExecShellMode::for_session(            UnifiedExecFeatureMode::Direct,            ToolUserShellType::Zsh,            Some(&shell),            Some(&exe),        ),        UnifiedExecShellMode::Direct    );}