mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
Warn when a CLI model is absent from the ChatGPT model list (#60270)
## What changed Show a startup warning when the active model matches the CLI model override but is missing from the ChatGPT model list, for ChatGPT accounts using the OpenAI provider. Suggest checking the spelling or choosing another model with `/model`, while preserving the selected model and submitting queued startup input. Reuse the transcript-visible warning helper for this notice and existing usage warnings. ## Testing Extend the startup test to check the warning text, preserved model selection, and queued input submission. GitOrigin-RevId: bb1e8c415346bf271e25ef4e8571c13b4bc2c8c8
This commit is contained in:
@@ -16,6 +16,7 @@ use crate::app_server_session::source_agent_path;
|
||||
use crate::app_server_session::thread_blocks_direct_input;
|
||||
use crate::chatwidget::ThreadInputStateRestoreMode;
|
||||
use crate::streaming::commit_tick::CommitTickScope;
|
||||
use codex_model_provider_info::OPENAI_PROVIDER_ID;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@@ -1108,6 +1109,20 @@ impl App {
|
||||
self.enqueue_primary_thread_session(started.session, started.turns)
|
||||
.await?;
|
||||
self.apply_backend_banner_fallback(app_server).await;
|
||||
if let Some(model) = self.harness_overrides.model.as_deref()
|
||||
&& model == self.chat_widget.current_model()
|
||||
&& self.chat_widget.has_chatgpt_account()
|
||||
&& self.chat_widget.config_ref().model_provider_id == OPENAI_PROVIDER_ID
|
||||
&& !self
|
||||
.model_catalog
|
||||
.models
|
||||
.iter()
|
||||
.any(|preset| preset.model == model)
|
||||
{
|
||||
self.chat_widget.add_to_history(history_cell::new_visible_warning_event(format!(
|
||||
"Your ChatGPT model list doesn't include `{model}`. Check the spelling or use /model to choose another model."
|
||||
)));
|
||||
}
|
||||
if let Some(notice) = self.pending_server_version_notice.take() {
|
||||
self.chat_widget.add_server_version_warning(notice);
|
||||
}
|
||||
|
||||
@@ -1365,7 +1365,10 @@ async fn known_thread_started_preserves_session_without_reading_unmaterialized_r
|
||||
|
||||
#[tokio::test]
|
||||
async fn startup_thread_started_submits_queued_startup_input() {
|
||||
let (mut app, _app_event_rx, mut op_rx) = make_test_app_with_channels().await;
|
||||
let (mut app, mut events, mut op_rx) = make_test_app_with_channels().await;
|
||||
set_chatgpt_auth(&mut app.chat_widget);
|
||||
let model = "unlisted-model";
|
||||
app.harness_overrides.model = Some(model.into());
|
||||
app.pending_startup_thread_start = true;
|
||||
app.chat_widget
|
||||
.set_queue_submissions_until_session_configured(/*queue*/ true);
|
||||
@@ -1384,11 +1387,13 @@ async fn startup_thread_started_submits_queued_startup_input() {
|
||||
))
|
||||
.await
|
||||
.expect("embedded app server");
|
||||
let thread_id = ThreadId::new();
|
||||
let mut session = test_thread_session(ThreadId::new(), test_path_buf("/tmp/project"));
|
||||
session.model = model.into();
|
||||
session.model_provider_id = "openai".into();
|
||||
app.handle_startup_thread_started(
|
||||
&mut app_server,
|
||||
Ok(AppServerStartedThread {
|
||||
session: test_thread_session(thread_id, test_path_buf("/tmp/project")),
|
||||
session,
|
||||
turns: Vec::new(),
|
||||
blocks_direct_input: false,
|
||||
task_tools_available: false,
|
||||
@@ -1397,6 +1402,19 @@ async fn startup_thread_started_submits_queued_startup_input() {
|
||||
.await
|
||||
.expect("startup thread should attach");
|
||||
|
||||
let warnings: Vec<_> = std::iter::from_fn(|| events.try_recv().ok())
|
||||
.filter_map(|event| match event {
|
||||
AppEvent::InsertHistoryCell(cell) if !cell.warning_entries().is_empty() => {
|
||||
Some(lines_to_single_string(&cell.display_lines(/*width*/ 80)))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
insta::assert_snapshot!(warnings.join("\n"), @r"
|
||||
⚠ Your ChatGPT model list doesn't include `unlisted-model`. Check the spelling
|
||||
or use /model to choose another model.
|
||||
");
|
||||
assert_eq!(app.chat_widget.current_model(), model);
|
||||
match next_user_turn_op(&mut op_rx) {
|
||||
Op::UserTurn { items, .. } => assert_eq!(
|
||||
items,
|
||||
|
||||
@@ -393,7 +393,7 @@ impl ChatWidget {
|
||||
|
||||
if !warnings.is_empty() {
|
||||
for warning in warnings {
|
||||
self.add_to_history(history_cell::new_usage_warning_event(warning));
|
||||
self.add_to_history(history_cell::new_visible_warning_event(warning));
|
||||
}
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ pub(crate) fn new_warning_event(message: String) -> WarningHistoryCell {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_usage_warning_event(message: String) -> WarningHistoryCell {
|
||||
pub(crate) fn new_visible_warning_event(message: String) -> WarningHistoryCell {
|
||||
WarningHistoryCell {
|
||||
visible_in_transcript: true,
|
||||
..new_warning_event(message)
|
||||
|
||||
@@ -6,12 +6,12 @@ use pretty_assertions::assert_eq;
|
||||
#[test]
|
||||
fn usage_warnings_render_in_both_transcripts_including_composites() {
|
||||
let message = "Only 8% of your 5h limit remains. Run /status for details.";
|
||||
let usage = new_usage_warning_event(message.into());
|
||||
let usage = new_visible_warning_event(message.into());
|
||||
let diagnostic = new_warning_event(message.into());
|
||||
let composite = CompositeHistoryCell::new(vec![
|
||||
Box::new(PlainHistoryCell::new(vec!["Earlier output".into()])),
|
||||
Box::new(new_warning_event("Hidden diagnostic".into())),
|
||||
Box::new(new_usage_warning_event(message.into())),
|
||||
Box::new(new_visible_warning_event(message.into())),
|
||||
]);
|
||||
assert_eq!(usage.warning_entries(), diagnostic.warning_entries());
|
||||
for mode in [HistoryRenderMode::Rich, HistoryRenderMode::Raw] {
|
||||
|
||||
Reference in New Issue
Block a user