mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
80ebc80be5
Fast Mode status was still tied to one model name in the TUI and model-list plumbing. This changes the model metadata shape so a model can advertise additional speed tiers, carries that field through the app-server model list, and uses it to decide when to show Fast Mode status. For people using Codex, the behavior is intended to stay the same for existing models. Fast Mode still requires the existing signed-in / feature-gated path; the difference is that the UI can now recognize any model the model list marks as Fast-capable, instead of requiring a new client-side slug check.
115 lines
4.8 KiB
Rust
115 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,
|
|
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),
|
|
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;
|