mirror of
https://github.com/openai/codex.git
synced 2026-05-20 03:05:02 +00:00
Adds max_context_window to model metadata and routes core context-window reads through resolved model info. Config model_context_window overrides are clamped to max_context_window when present; without an override, the model context_window is used.
122 lines
5.0 KiB
Rust
122 lines
5.0 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(
|
|
model
|
|
.max_context_window
|
|
.map_or(context_window, |max_context_window| {
|
|
context_window.min(max_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,
|
|
additional_speed_tiers: Vec::new(),
|
|
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),
|
|
max_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;
|