mirror of
https://github.com/openai/codex.git
synced 2026-10-27 18:48:37 +00:00
## Summary - split `models-manager` out of `core` and add `ModelsManagerConfig` plus `Config::to_models_manager_config()` so model metadata paths stop depending on `core::Config` - move login-owned/auth-owned code out of `core` into `codex-login`, move model provider config into `codex-model-provider-info`, move API bridge mapping into `codex-api`, move protocol-owned types/impls into `codex-protocol`, and move response debug helpers into a dedicated `response-debug-context` crate - move feedback tag emission into `codex-feedback`, relocate tests to the crates that now own the code, and keep broad temporary re-exports so this PR avoids a giant import-only rewrite ## Major moves and decisions - created `codex-models-manager` as the owner for model cache/catalog/config/model info logic, including the new `ModelsManagerConfig` struct - created `codex-model-provider-info` as the owner for provider config parsing/defaults and kept temporary `codex-login`/`codex-core` re-exports for old import paths - moved `api_bridge` error mapping + `CoreAuthProvider` into `codex-api`, while `codex-login::api_bridge` temporarily re-exports those symbols and keeps the `auth_provider_from_auth` wrapper - moved `auth_env_telemetry` and `provider_auth` ownership to `codex-login` - moved `CodexErr` ownership to `codex-protocol::error`, plus `StreamOutput`, `bytes_to_string_smart`, and network policy helpers to protocol-owned modules - created `codex-response-debug-context` for `extract_response_debug_context`, `telemetry_transport_error_message`, and related response-debug plumbing instead of leaving that behavior in `core` - moved `FeedbackRequestTags`, `emit_feedback_request_tags`, and `emit_feedback_request_tags_with_auth_env` to `codex-feedback` - deferred removal of temporary re-exports and the mechanical import rewrites to a stacked follow-up PR so this PR stays reviewable ## Test moves - moved auth refresh coverage from `core/tests/suite/auth_refresh.rs` to `login/tests/suite/auth_refresh.rs` - moved text encoding coverage from `core/tests/suite/text_encoding_fix.rs` to `protocol/src/exec_output_tests.rs` - moved model info override coverage from `core/tests/suite/model_info_overrides.rs` to `models-manager/src/model_info_overrides_tests.rs` --------- Co-authored-by: Codex <noreply@openai.com>
114 lines
4.8 KiB
Rust
114 lines
4.8 KiB
Rust
use codex_protocol::config_types::ReasoningSummary;
|
|
use codex_protocol::openai_models::ConfigShellToolType;
|
|
use codex_protocol::openai_models::ModelInfo;
|
|
use codex_protocol::openai_models::ModelInstructionsVariables;
|
|
use codex_protocol::openai_models::ModelMessages;
|
|
use codex_protocol::openai_models::ModelVisibility;
|
|
use codex_protocol::openai_models::TruncationMode;
|
|
use codex_protocol::openai_models::TruncationPolicyConfig;
|
|
use codex_protocol::openai_models::WebSearchToolType;
|
|
use codex_protocol::openai_models::default_input_modalities;
|
|
|
|
use crate::config::ModelsManagerConfig;
|
|
use codex_utils_output_truncation::approx_bytes_for_tokens;
|
|
use tracing::warn;
|
|
|
|
pub const BASE_INSTRUCTIONS: &str = include_str!("../prompt.md");
|
|
const DEFAULT_PERSONALITY_HEADER: &str = "You are Codex, a coding agent based on GPT-5. You and the user share the same workspace and collaborate to achieve the user's goals.";
|
|
const LOCAL_FRIENDLY_TEMPLATE: &str =
|
|
"You optimize for team morale and being a supportive teammate as much as code quality.";
|
|
const LOCAL_PRAGMATIC_TEMPLATE: &str = "You are a deeply pragmatic, effective software engineer.";
|
|
const PERSONALITY_PLACEHOLDER: &str = "{{ personality }}";
|
|
|
|
pub fn with_config_overrides(mut model: ModelInfo, config: &ModelsManagerConfig) -> ModelInfo {
|
|
if let Some(supports_reasoning_summaries) = config.model_supports_reasoning_summaries
|
|
&& supports_reasoning_summaries
|
|
{
|
|
model.supports_reasoning_summaries = true;
|
|
}
|
|
if let Some(context_window) = config.model_context_window {
|
|
model.context_window = Some(context_window);
|
|
}
|
|
if let Some(auto_compact_token_limit) = config.model_auto_compact_token_limit {
|
|
model.auto_compact_token_limit = Some(auto_compact_token_limit);
|
|
}
|
|
if let Some(token_limit) = config.tool_output_token_limit {
|
|
model.truncation_policy = match model.truncation_policy.mode {
|
|
TruncationMode::Bytes => {
|
|
let byte_limit =
|
|
i64::try_from(approx_bytes_for_tokens(token_limit)).unwrap_or(i64::MAX);
|
|
TruncationPolicyConfig::bytes(byte_limit)
|
|
}
|
|
TruncationMode::Tokens => {
|
|
let limit = i64::try_from(token_limit).unwrap_or(i64::MAX);
|
|
TruncationPolicyConfig::tokens(limit)
|
|
}
|
|
};
|
|
}
|
|
|
|
if let Some(base_instructions) = &config.base_instructions {
|
|
model.base_instructions = base_instructions.clone();
|
|
model.model_messages = None;
|
|
} else if !config.personality_enabled {
|
|
model.model_messages = None;
|
|
}
|
|
|
|
model
|
|
}
|
|
|
|
/// Build a minimal fallback model descriptor for missing/unknown slugs.
|
|
pub fn model_info_from_slug(slug: &str) -> ModelInfo {
|
|
warn!("Unknown model {slug} is used. This will use fallback model metadata.");
|
|
ModelInfo {
|
|
slug: slug.to_string(),
|
|
display_name: slug.to_string(),
|
|
description: None,
|
|
default_reasoning_level: None,
|
|
supported_reasoning_levels: Vec::new(),
|
|
shell_type: ConfigShellToolType::Default,
|
|
visibility: ModelVisibility::None,
|
|
supported_in_api: true,
|
|
priority: 99,
|
|
availability_nux: None,
|
|
upgrade: None,
|
|
base_instructions: BASE_INSTRUCTIONS.to_string(),
|
|
model_messages: local_personality_messages_for_slug(slug),
|
|
supports_reasoning_summaries: false,
|
|
default_reasoning_summary: ReasoningSummary::Auto,
|
|
support_verbosity: false,
|
|
default_verbosity: None,
|
|
apply_patch_tool_type: None,
|
|
web_search_tool_type: WebSearchToolType::Text,
|
|
truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000),
|
|
supports_parallel_tool_calls: false,
|
|
supports_image_detail_original: 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(),
|
|
used_fallback_model_metadata: true, // this is the fallback model metadata
|
|
supports_search_tool: false,
|
|
}
|
|
}
|
|
|
|
fn local_personality_messages_for_slug(slug: &str) -> Option<ModelMessages> {
|
|
match slug {
|
|
"gpt-5.2-codex" | "exp-codex-personality" => Some(ModelMessages {
|
|
instructions_template: Some(format!(
|
|
"{DEFAULT_PERSONALITY_HEADER}\n\n{PERSONALITY_PLACEHOLDER}\n\n{BASE_INSTRUCTIONS}"
|
|
)),
|
|
instructions_variables: Some(ModelInstructionsVariables {
|
|
personality_default: Some(String::new()),
|
|
personality_friendly: Some(LOCAL_FRIENDLY_TEMPLATE.to_string()),
|
|
personality_pragmatic: Some(LOCAL_PRAGMATIC_TEMPLATE.to_string()),
|
|
}),
|
|
}),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "model_info_tests.rs"]
|
|
mod tests;
|