From 16f9414b372ec16a6a4cde12d44fd1407add0364 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 30 Mar 2026 15:48:58 -0600 Subject: [PATCH] codex: address PR review feedback (#16274) --- codex-rs/core/src/codex.rs | 22 +++++++++++++-- codex-rs/core/src/codex_tests.rs | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index dd6b94aa3d..4e4d3030dc 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -33,6 +33,7 @@ use crate::models_manager::manager::RefreshStrategy; use crate::parse_command::parse_command; use crate::parse_turn_item; use crate::path_utils::normalize_for_native_workdir; +use crate::personalities::PersonalityCatalog; use crate::personalities::catalog_for_config; use crate::realtime_conversation::RealtimeConversationManager; use crate::realtime_conversation::handle_audio as handle_realtime_conversation_audio; @@ -2624,17 +2625,33 @@ impl Session { }; let shell = self.user_shell(); let exec_policy = self.services.exec_policy.current(); + let personality_catalog = self.personality_catalog_for_turn_context(current_context); crate::context_manager::updates::build_settings_update_items( reference_context_item, previous_turn_settings.as_ref(), current_context, shell.as_ref(), exec_policy.as_ref(), - self.services.personality_catalog.as_ref(), + &personality_catalog, self.features.enabled(Feature::Personality), ) } + fn personality_catalog_for_turn_context( + &self, + turn_context: &TurnContext, + ) -> PersonalityCatalog { + if turn_context + .personality + .as_ref() + .is_some_and(|personality| !personality.is_builtin()) + { + catalog_for_config(turn_context.config.as_ref()) + } else { + self.services.personality_catalog.as_ref().clone() + } + } + /// Persist the event to rollout and send it to clients. pub(crate) async fn send_event(&self, turn_context: &TurnContext, msg: EventMsg) { let legacy_source = msg.clone(); @@ -3619,6 +3636,7 @@ impl Session { && let Some(personality) = turn_context.personality.clone() { let model_info = turn_context.model_info.clone(); + let personality_catalog = self.personality_catalog_for_turn_context(turn_context); let has_baked_personality = personality.is_builtin() && model_info.supports_personality() && base_instructions @@ -3627,7 +3645,7 @@ impl Session { && let Some(personality_message) = crate::context_manager::updates::personality_message_for( &model_info, - &self.services.personality_catalog, + &personality_catalog, &personality, ) { diff --git a/codex-rs/core/src/codex_tests.rs b/codex-rs/core/src/codex_tests.rs index 246cffba92..6997a64588 100644 --- a/codex-rs/core/src/codex_tests.rs +++ b/codex-rs/core/src/codex_tests.rs @@ -70,6 +70,7 @@ use codex_network_proxy::NetworkProxyConfig; use codex_otel::TelemetryAuthMode; use codex_protocol::config_types::CollaborationMode; use codex_protocol::config_types::ModeKind; +use codex_protocol::config_types::Personality; use codex_protocol::config_types::Settings; use codex_protocol::models::BaseInstructions; use codex_protocol::models::ContentItem; @@ -3869,6 +3870,53 @@ async fn build_settings_update_items_emits_realtime_end_when_session_stops_being ); } +#[tokio::test] +async fn build_settings_update_items_reload_custom_personality_catalog_for_running_session() { + let (session, previous_context) = make_session_and_context().await; + let personality_name = "captain-late"; + let personality_body = "Ahoy. Keep the answer seaworthy."; + let personalities_dir = previous_context.config.codex_home.join("personalities"); + std::fs::create_dir_all(&personalities_dir).expect("create personalities dir"); + std::fs::write( + personalities_dir.join(format!("{personality_name}.md")), + format!( + "---\nname: {personality_name}\ndescription: test personality\n---\n\n{personality_body}\n" + ), + ) + .expect("write custom personality"); + + assert_eq!( + session + .services + .personality_catalog + .get(&Personality::from(personality_name)), + None + ); + + let mut current_context = previous_context + .with_model( + previous_context.model_info.slug.clone(), + &session.services.models_manager, + ) + .await; + current_context.personality = Some(Personality::from(personality_name)); + + let update_items = session + .build_settings_update_items( + Some(&previous_context.to_turn_context_item()), + ¤t_context, + ) + .await; + + let developer_texts = developer_input_texts(&update_items); + assert!( + developer_texts + .iter() + .any(|text| text.contains(personality_body)), + "expected custom personality update, got {developer_texts:?}" + ); +} + #[tokio::test] async fn build_settings_update_items_uses_previous_turn_settings_for_realtime_end() { let (session, previous_context) = make_session_and_context().await;