Don't show the model for apikey (#3607)

This commit is contained in:
Ahmed Ibrahim
2025-09-14 21:32:18 -04:00
committed by GitHub
parent e5dd7f0934
commit 2ad6a37192
5 changed files with 87 additions and 58 deletions

View File

@@ -1,4 +1,6 @@
use codex_core::config::SWIFTFOX_MEDIUM_MODEL;
use codex_core::protocol_config_types::ReasoningEffort; use codex_core::protocol_config_types::ReasoningEffort;
use codex_protocol::mcp_protocol::AuthMode;
/// A simple preset pairing a model slug with a reasoning effort. /// A simple preset pairing a model slug with a reasoning effort.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@@ -15,61 +17,65 @@ pub struct ModelPreset {
pub effort: Option<ReasoningEffort>, pub effort: Option<ReasoningEffort>,
} }
/// Built-in list of model presets that pair a model with a reasoning effort. const PRESETS: &[ModelPreset] = &[
/// ModelPreset {
/// Keep this UI-agnostic so it can be reused by both TUI and MCP server. id: "swiftfox-low",
pub fn builtin_model_presets() -> &'static [ModelPreset] { label: "swiftfox low",
// Order groups swiftfox variants before gpt-5 presets, each from minimal to high. description: "",
const PRESETS: &[ModelPreset] = &[ model: "swiftfox",
ModelPreset { effort: Some(ReasoningEffort::Low),
id: "swiftfox-low", },
label: "swiftfox low", ModelPreset {
description: "", id: "swiftfox-medium",
model: "swiftfox", label: "swiftfox medium",
effort: Some(ReasoningEffort::Low), description: "",
}, model: "swiftfox",
ModelPreset { effort: None,
id: "swiftfox-medium", },
label: "swiftfox medium", ModelPreset {
description: "", id: "swiftfox-high",
model: "swiftfox", label: "swiftfox high",
effort: None, description: "",
}, model: "swiftfox",
ModelPreset { effort: Some(ReasoningEffort::High),
id: "swiftfox-high", },
label: "swiftfox high", ModelPreset {
description: "", id: "gpt-5-minimal",
model: "swiftfox", label: "gpt-5 minimal",
effort: Some(ReasoningEffort::High), description: "— fastest responses with limited reasoning; ideal for coding, instructions, or lightweight tasks",
}, model: "gpt-5",
ModelPreset { effort: Some(ReasoningEffort::Minimal),
id: "gpt-5-minimal", },
label: "gpt-5 minimal", ModelPreset {
description: "— fastest responses with limited reasoning; ideal for coding, instructions, or lightweight tasks", id: "gpt-5-low",
model: "gpt-5", label: "gpt-5 low",
effort: Some(ReasoningEffort::Minimal), description: "— balances speed with some reasoning; useful for straightforward queries and short explanations",
}, model: "gpt-5",
ModelPreset { effort: Some(ReasoningEffort::Low),
id: "gpt-5-low", },
label: "gpt-5 low", ModelPreset {
description: "— balances speed with some reasoning; useful for straightforward queries and short explanations", id: "gpt-5-medium",
model: "gpt-5", label: "gpt-5 medium",
effort: Some(ReasoningEffort::Low), description: "— default setting; provides a solid balance of reasoning depth and latency for general-purpose tasks",
}, model: "gpt-5",
ModelPreset { effort: Some(ReasoningEffort::Medium),
id: "gpt-5-medium", },
label: "gpt-5 medium", ModelPreset {
description: "— default setting; provides a solid balance of reasoning depth and latency for general-purpose tasks", id: "gpt-5-high",
model: "gpt-5", label: "gpt-5 high",
effort: Some(ReasoningEffort::Medium), description: "— maximizes reasoning depth for complex or ambiguous problems",
}, model: "gpt-5",
ModelPreset { effort: Some(ReasoningEffort::High),
id: "gpt-5-high", },
label: "gpt-5 high", ];
description: "— maximizes reasoning depth for complex or ambiguous problems",
model: "gpt-5", pub fn builtin_model_presets(auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
effort: Some(ReasoningEffort::High), match auth_mode {
}, Some(AuthMode::ApiKey) => PRESETS
]; .iter()
PRESETS .copied()
.filter(|p| !p.model.contains(SWIFTFOX_MEDIUM_MODEL))
.collect(),
_ => PRESETS.to_vec(),
}
} }

View File

@@ -38,6 +38,7 @@ pub(crate) struct App {
pub(crate) server: Arc<ConversationManager>, pub(crate) server: Arc<ConversationManager>,
pub(crate) app_event_tx: AppEventSender, pub(crate) app_event_tx: AppEventSender,
pub(crate) chat_widget: ChatWidget, pub(crate) chat_widget: ChatWidget,
pub(crate) auth_manager: Arc<AuthManager>,
/// Config is stored here so we can recreate ChatWidgets as needed. /// Config is stored here so we can recreate ChatWidgets as needed.
pub(crate) config: Config, pub(crate) config: Config,
@@ -88,6 +89,7 @@ impl App {
initial_prompt: initial_prompt.clone(), initial_prompt: initial_prompt.clone(),
initial_images: initial_images.clone(), initial_images: initial_images.clone(),
enhanced_keys_supported, enhanced_keys_supported,
auth_manager: auth_manager.clone(),
}; };
ChatWidget::new(init, conversation_manager.clone()) ChatWidget::new(init, conversation_manager.clone())
} }
@@ -109,6 +111,7 @@ impl App {
initial_prompt: initial_prompt.clone(), initial_prompt: initial_prompt.clone(),
initial_images: initial_images.clone(), initial_images: initial_images.clone(),
enhanced_keys_supported, enhanced_keys_supported,
auth_manager: auth_manager.clone(),
}; };
ChatWidget::new_from_existing( ChatWidget::new_from_existing(
init, init,
@@ -124,6 +127,7 @@ impl App {
server: conversation_manager, server: conversation_manager,
app_event_tx, app_event_tx,
chat_widget, chat_widget,
auth_manager: auth_manager.clone(),
config, config,
active_profile, active_profile,
file_search, file_search,
@@ -205,6 +209,7 @@ impl App {
initial_prompt: None, initial_prompt: None,
initial_images: Vec::new(), initial_images: Vec::new(),
enhanced_keys_supported: self.enhanced_keys_supported, enhanced_keys_supported: self.enhanced_keys_supported,
auth_manager: self.auth_manager.clone(),
}; };
self.chat_widget = ChatWidget::new(init, self.server.clone()); self.chat_widget = ChatWidget::new(init, self.server.clone());
tui.frame_requester().schedule_frame(); tui.frame_requester().schedule_frame();
@@ -418,6 +423,7 @@ mod tests {
use crate::app_backtrack::BacktrackState; use crate::app_backtrack::BacktrackState;
use crate::chatwidget::tests::make_chatwidget_manual_with_sender; use crate::chatwidget::tests::make_chatwidget_manual_with_sender;
use crate::file_search::FileSearchManager; use crate::file_search::FileSearchManager;
use codex_core::AuthManager;
use codex_core::CodexAuth; use codex_core::CodexAuth;
use codex_core::ConversationManager; use codex_core::ConversationManager;
use std::sync::Arc; use std::sync::Arc;
@@ -430,12 +436,15 @@ mod tests {
let server = Arc::new(ConversationManager::with_auth(CodexAuth::from_api_key( let server = Arc::new(ConversationManager::with_auth(CodexAuth::from_api_key(
"Test API Key", "Test API Key",
))); )));
let auth_manager =
AuthManager::from_auth_for_testing(CodexAuth::from_api_key("Test API Key"));
let file_search = FileSearchManager::new(config.cwd.clone(), app_event_tx.clone()); let file_search = FileSearchManager::new(config.cwd.clone(), app_event_tx.clone());
App { App {
server, server,
app_event_tx, app_event_tx,
chat_widget, chat_widget,
auth_manager,
config, config,
active_profile: None, active_profile: None,
file_search, file_search,

View File

@@ -335,6 +335,7 @@ impl App {
initial_prompt: None, initial_prompt: None,
initial_images: Vec::new(), initial_images: Vec::new(),
enhanced_keys_supported: self.enhanced_keys_supported, enhanced_keys_supported: self.enhanced_keys_supported,
auth_manager: self.auth_manager.clone(),
}; };
self.chat_widget = self.chat_widget =
crate::chatwidget::ChatWidget::new_from_existing(init, conv, session_configured); crate::chatwidget::ChatWidget::new_from_existing(init, conv, session_configured);

View File

@@ -82,6 +82,7 @@ use codex_common::approval_presets::ApprovalPreset;
use codex_common::approval_presets::builtin_approval_presets; use codex_common::approval_presets::builtin_approval_presets;
use codex_common::model_presets::ModelPreset; use codex_common::model_presets::ModelPreset;
use codex_common::model_presets::builtin_model_presets; use codex_common::model_presets::builtin_model_presets;
use codex_core::AuthManager;
use codex_core::ConversationManager; use codex_core::ConversationManager;
use codex_core::protocol::AskForApproval; use codex_core::protocol::AskForApproval;
use codex_core::protocol::SandboxPolicy; use codex_core::protocol::SandboxPolicy;
@@ -103,6 +104,7 @@ pub(crate) struct ChatWidgetInit {
pub(crate) initial_prompt: Option<String>, pub(crate) initial_prompt: Option<String>,
pub(crate) initial_images: Vec<PathBuf>, pub(crate) initial_images: Vec<PathBuf>,
pub(crate) enhanced_keys_supported: bool, pub(crate) enhanced_keys_supported: bool,
pub(crate) auth_manager: Arc<AuthManager>,
} }
pub(crate) struct ChatWidget { pub(crate) struct ChatWidget {
@@ -111,6 +113,7 @@ pub(crate) struct ChatWidget {
bottom_pane: BottomPane, bottom_pane: BottomPane,
active_exec_cell: Option<ExecCell>, active_exec_cell: Option<ExecCell>,
config: Config, config: Config,
auth_manager: Arc<AuthManager>,
session_header: SessionHeader, session_header: SessionHeader,
initial_user_message: Option<UserMessage>, initial_user_message: Option<UserMessage>,
token_info: Option<TokenUsageInfo>, token_info: Option<TokenUsageInfo>,
@@ -646,6 +649,7 @@ impl ChatWidget {
initial_prompt, initial_prompt,
initial_images, initial_images,
enhanced_keys_supported, enhanced_keys_supported,
auth_manager,
} = common; } = common;
let mut rng = rand::rng(); let mut rng = rand::rng();
let placeholder = EXAMPLE_PROMPTS[rng.random_range(0..EXAMPLE_PROMPTS.len())].to_string(); let placeholder = EXAMPLE_PROMPTS[rng.random_range(0..EXAMPLE_PROMPTS.len())].to_string();
@@ -665,6 +669,7 @@ impl ChatWidget {
}), }),
active_exec_cell: None, active_exec_cell: None,
config: config.clone(), config: config.clone(),
auth_manager,
session_header: SessionHeader::new(config.model.clone()), session_header: SessionHeader::new(config.model.clone()),
initial_user_message: create_initial_user_message( initial_user_message: create_initial_user_message(
initial_prompt.unwrap_or_default(), initial_prompt.unwrap_or_default(),
@@ -697,6 +702,7 @@ impl ChatWidget {
initial_prompt, initial_prompt,
initial_images, initial_images,
enhanced_keys_supported, enhanced_keys_supported,
auth_manager,
} = common; } = common;
let mut rng = rand::rng(); let mut rng = rand::rng();
let placeholder = EXAMPLE_PROMPTS[rng.random_range(0..EXAMPLE_PROMPTS.len())].to_string(); let placeholder = EXAMPLE_PROMPTS[rng.random_range(0..EXAMPLE_PROMPTS.len())].to_string();
@@ -718,6 +724,7 @@ impl ChatWidget {
}), }),
active_exec_cell: None, active_exec_cell: None,
config: config.clone(), config: config.clone(),
auth_manager,
session_header: SessionHeader::new(config.model.clone()), session_header: SessionHeader::new(config.model.clone()),
initial_user_message: create_initial_user_message( initial_user_message: create_initial_user_message(
initial_prompt.unwrap_or_default(), initial_prompt.unwrap_or_default(),
@@ -1188,7 +1195,8 @@ impl ChatWidget {
pub(crate) fn open_model_popup(&mut self) { pub(crate) fn open_model_popup(&mut self) {
let current_model = self.config.model.clone(); let current_model = self.config.model.clone();
let current_effort = self.config.model_reasoning_effort; let current_effort = self.config.model_reasoning_effort;
let presets: &[ModelPreset] = builtin_model_presets(); let auth_mode = self.auth_manager.auth().map(|auth| auth.mode);
let presets: Vec<ModelPreset> = builtin_model_presets(auth_mode);
let mut items: Vec<SelectionItem> = Vec::new(); let mut items: Vec<SelectionItem> = Vec::new();
for preset in presets.iter() { for preset in presets.iter() {

View File

@@ -1,6 +1,7 @@
use super::*; use super::*;
use crate::app_event::AppEvent; use crate::app_event::AppEvent;
use crate::app_event_sender::AppEventSender; use crate::app_event_sender::AppEventSender;
use codex_core::AuthManager;
use codex_core::CodexAuth; use codex_core::CodexAuth;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides; use codex_core::config::ConfigOverrides;
@@ -195,6 +196,7 @@ async fn helpers_are_available_and_do_not_panic() {
let conversation_manager = Arc::new(ConversationManager::with_auth(CodexAuth::from_api_key( let conversation_manager = Arc::new(ConversationManager::with_auth(CodexAuth::from_api_key(
"test", "test",
))); )));
let auth_manager = AuthManager::from_auth_for_testing(CodexAuth::from_api_key("test"));
let init = ChatWidgetInit { let init = ChatWidgetInit {
config: cfg, config: cfg,
frame_requester: FrameRequester::test_dummy(), frame_requester: FrameRequester::test_dummy(),
@@ -202,6 +204,7 @@ async fn helpers_are_available_and_do_not_panic() {
initial_prompt: None, initial_prompt: None,
initial_images: Vec::new(), initial_images: Vec::new(),
enhanced_keys_supported: false, enhanced_keys_supported: false,
auth_manager,
}; };
let mut w = ChatWidget::new(init, conversation_manager); let mut w = ChatWidget::new(init, conversation_manager);
// Basic construction sanity. // Basic construction sanity.
@@ -226,12 +229,14 @@ fn make_chatwidget_manual() -> (
placeholder_text: "Ask Codex to do anything".to_string(), placeholder_text: "Ask Codex to do anything".to_string(),
disable_paste_burst: false, disable_paste_burst: false,
}); });
let auth_manager = AuthManager::from_auth_for_testing(CodexAuth::from_api_key("test"));
let widget = ChatWidget { let widget = ChatWidget {
app_event_tx, app_event_tx,
codex_op_tx: op_tx, codex_op_tx: op_tx,
bottom_pane: bottom, bottom_pane: bottom,
active_exec_cell: None, active_exec_cell: None,
config: cfg.clone(), config: cfg.clone(),
auth_manager,
session_header: SessionHeader::new(cfg.model.clone()), session_header: SessionHeader::new(cfg.model.clone()),
initial_user_message: None, initial_user_message: None,
token_info: None, token_info: None,