Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion codex-rs/tui/src/app/event_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,8 +1303,10 @@ impl App {
}
AppEvent::PersistServiceTierSelection { service_tier } => {
self.refresh_status_line();
let profile = self.active_profile.as_deref();
self.config.service_tier = service_tier.clone();
self.sync_active_thread_service_tier_to_cached_session()
.await;
let profile = self.active_profile.as_deref();
let edits = crate::config_update::build_service_tier_selection_edits(
profile,
service_tier.as_deref(),
Expand Down
69 changes: 69 additions & 0 deletions codex-rs/tui/src/app/thread_session_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@ use codex_protocol::models::ActivePermissionProfile;
use codex_protocol::models::PermissionProfile;

impl App {
pub(super) async fn sync_active_thread_service_tier_to_cached_session(&mut self) {
let Some(active_thread_id) = self.active_thread_id else {
return;
};

let service_tier = self.chat_widget.current_service_tier().map(str::to_string);
let update_session = |session: &mut ThreadSessionState| {
session.service_tier = service_tier.clone();
};

if self.primary_thread_id == Some(active_thread_id)
&& let Some(session) = self.primary_session_configured.as_mut()
{
update_session(session);
}

if let Some(channel) = self.thread_event_channels.get(&active_thread_id) {
let mut store = channel.store.lock().await;
if let Some(session) = store.session.as_mut() {
update_session(session);
}
}
}

pub(super) async fn sync_active_thread_permission_settings_to_cached_session(&mut self) {
let Some(active_thread_id) = self.active_thread_id else {
return;
Expand Down Expand Up @@ -125,6 +149,7 @@ mod tests {
use crate::test_support::test_path_buf;
use codex_app_server_protocol::AskForApproval;
use codex_config::types::ApprovalsReviewer;
use codex_protocol::config_types::ServiceTier;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_WORKSPACE;
use codex_protocol::models::ManagedFileSystemPermissions;
use codex_protocol::models::PermissionProfile;
Expand Down Expand Up @@ -316,6 +341,50 @@ mod tests {
assert_eq!(store_session, Some(expected_session));
}

#[tokio::test]
async fn service_tier_sync_updates_active_cached_session() {
let mut app = make_test_app().await;
let thread_id =
ThreadId::from_string("00000000-0000-0000-0000-000000000406").expect("valid thread");
let session = ThreadSessionState {
service_tier: Some(ServiceTier::Fast.request_value().to_string()),
..test_thread_session(thread_id, test_path_buf("/tmp/main"))
};

app.primary_thread_id = Some(thread_id);
app.active_thread_id = Some(thread_id);
app.primary_session_configured = Some(session.clone());
app.thread_event_channels.insert(
thread_id,
ThreadEventChannel::new_with_session(/*capacity*/ 4, session.clone(), Vec::new()),
);
app.chat_widget.handle_thread_session(session);
app.chat_widget.set_service_tier(/*service_tier*/ None);

app.sync_active_thread_service_tier_to_cached_session()
.await;

let expected_session = ThreadSessionState {
service_tier: None,
..test_thread_session(thread_id, test_path_buf("/tmp/main"))
};
assert_eq!(
app.primary_session_configured,
Some(expected_session.clone())
);

let store_session = app
.thread_event_channels
.get(&thread_id)
.expect("thread channel")
.store
.lock()
.await
.session
.clone();
assert_eq!(store_session, Some(expected_session));
}

#[tokio::test]
async fn thread_read_fallback_uses_active_permission_settings() {
let mut app = make_test_app().await;
Expand Down
Loading