mirror of
https://github.com/openai/codex.git
synced 2026-11-01 19:33:35 +00:00
## Why `codex-core` still had a `test-support` crate feature that was enabled by multiple consumers (`core_test_support`, `app_test_support`, and `codex-tui` dev-deps). That introduced a second feature-resolved shape of `codex-core`, which increases compile cost and cache fragmentation across the workspace. The same root issue previously affected `deterministic_process_ids`: we were using crate features as a test/runtime switch, and Cargo had to build extra variants of a very large crate. ## What Changed ### 1) Remove `test-support` as a crate feature - Deleted the feature declaration from `core/Cargo.toml`. - Removed `features = ["test-support"]` from: - `core/tests/common/Cargo.toml` - `app-server/tests/common/Cargo.toml` - `tui/Cargo.toml` (dev-dependency) - Removed Bazel `crate_features = ["test-support"]` from `core/BUILD.bazel`. ### 2) Keep test behavior without feature-gated crate variants - Converted test-only behavior toggles to **explicit runtime switches** backed by `AtomicBool`: - thread-manager test mode toggle - deterministic unified-exec process-id toggle - Enabled those toggles from `core_test_support` ctor so integration tests keep deterministic and test-friendly behavior. ### 3) Replace feature-gated helper APIs with always-compiled hidden helpers - APIs that were previously behind `#[cfg(feature = "test-support")]` are now available as `#[doc(hidden)]` test helpers, avoiding feature-split builds while preserving existing test call sites. ## Expected Benefits ### Concrete dependency-graph effect `cargo tree -p codex-core -e features` now shows only the default feature path for `codex-core`; there are no `test-support` or `deterministic_process_ids` feature edges remaining. ### Build-performance impact - Eliminates feature-driven duplicate `codex-core` compilation variants. - Improves cache reuse across test-support consumers that previously forced separate feature resolution. - Reduces rebuild churn when switching between targets that did and did not depend on the feature-enabled `codex-core` shape. ## Safety / behavior notes - Production behavior remains unchanged by default. - Test-only behavior is now explicit and opt-in via dedicated test toggles, with docstrings clarifying these must stay at default values in production. ## Validation - `just fmt` - `cargo test -p codex-core unified_exec::` - `cargo test -p codex-core --test all unified_exec -- --test-threads=1` - `cargo check -p app_test_support` - `cargo check -p codex-tui --tests` - `cargo check -p codex-core` - `cargo tree -p codex-core -e features`
90 lines
3.6 KiB
Rust
90 lines
3.6 KiB
Rust
use chrono::DateTime;
|
|
use chrono::Utc;
|
|
use codex_core::test_support::all_model_presets;
|
|
use codex_protocol::openai_models::ConfigShellToolType;
|
|
use codex_protocol::openai_models::ModelInfo;
|
|
use codex_protocol::openai_models::ModelPreset;
|
|
use codex_protocol::openai_models::ModelVisibility;
|
|
use codex_protocol::openai_models::TruncationPolicyConfig;
|
|
use codex_protocol::openai_models::default_input_modalities;
|
|
use serde_json::json;
|
|
use std::path::Path;
|
|
|
|
/// Convert a ModelPreset to ModelInfo for cache storage.
|
|
fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
|
|
ModelInfo {
|
|
slug: preset.id.clone(),
|
|
display_name: preset.display_name.clone(),
|
|
description: Some(preset.description.clone()),
|
|
default_reasoning_level: Some(preset.default_reasoning_effort),
|
|
supported_reasoning_levels: preset.supported_reasoning_efforts.clone(),
|
|
shell_type: ConfigShellToolType::ShellCommand,
|
|
visibility: if preset.show_in_picker {
|
|
ModelVisibility::List
|
|
} else {
|
|
ModelVisibility::Hide
|
|
},
|
|
supported_in_api: true,
|
|
priority,
|
|
upgrade: preset.upgrade.as_ref().map(|u| u.into()),
|
|
base_instructions: "base instructions".to_string(),
|
|
model_messages: None,
|
|
supports_reasoning_summaries: false,
|
|
support_verbosity: false,
|
|
default_verbosity: None,
|
|
apply_patch_tool_type: None,
|
|
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
|
supports_parallel_tool_calls: false,
|
|
context_window: Some(272_000),
|
|
auto_compact_token_limit: None,
|
|
effective_context_window_percent: 95,
|
|
experimental_supported_tools: Vec::new(),
|
|
input_modalities: default_input_modalities(),
|
|
prefer_websockets: false,
|
|
}
|
|
}
|
|
|
|
/// Write a models_cache.json file to the codex home directory.
|
|
/// This prevents ModelsManager from making network requests to refresh models.
|
|
/// The cache will be treated as fresh (within TTL) and used instead of fetching from the network.
|
|
/// Uses the built-in model presets from ModelsManager, converted to ModelInfo format.
|
|
pub fn write_models_cache(codex_home: &Path) -> std::io::Result<()> {
|
|
// Get all presets and filter for show_in_picker (same as builtin_model_presets does)
|
|
let presets: Vec<&ModelPreset> = all_model_presets()
|
|
.iter()
|
|
.filter(|preset| preset.show_in_picker)
|
|
.collect();
|
|
// Convert presets to ModelInfo, assigning priorities (lower = earlier in list).
|
|
// Priority is used for sorting, so the first model gets the lowest priority.
|
|
let models: Vec<ModelInfo> = presets
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(idx, preset)| {
|
|
// Lower priority = earlier in list.
|
|
let priority = idx as i32;
|
|
preset_to_info(preset, priority)
|
|
})
|
|
.collect();
|
|
|
|
write_models_cache_with_models(codex_home, models)
|
|
}
|
|
|
|
/// Write a models_cache.json file with specific models.
|
|
/// Useful when tests need specific models to be available.
|
|
pub fn write_models_cache_with_models(
|
|
codex_home: &Path,
|
|
models: Vec<ModelInfo>,
|
|
) -> std::io::Result<()> {
|
|
let cache_path = codex_home.join("models_cache.json");
|
|
// DateTime<Utc> serializes to RFC3339 format by default with serde
|
|
let fetched_at: DateTime<Utc> = Utc::now();
|
|
let client_version = codex_core::models_manager::client_version_to_whole();
|
|
let cache = json!({
|
|
"fetched_at": fetched_at,
|
|
"etag": null,
|
|
"client_version": client_version,
|
|
"models": models
|
|
});
|
|
std::fs::write(cache_path, serde_json::to_string_pretty(&cache)?)
|
|
}
|