@@ -3463,6 +3463,7 @@ async fn render_clear_ui_header_after_long_transcript_for_snapshot() -> String {
34633463 approval_policy : AskForApproval :: Never ,
34643464 approvals_reviewer : ApprovalsReviewer :: User ,
34653465 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
3466+ permission_profile : None ,
34663467 cwd : test_path_buf ( "/tmp/project" ) . abs ( ) ,
34673468 reasoning_effort : Some ( ReasoningEffortConfig :: High ) ,
34683469 history_log_id : 0 ,
@@ -4023,6 +4024,167 @@ fn active_turn_steer_race_extracts_actual_turn_id_from_mismatch() {
40234024 ) ;
40244025}
40254026
4027+ #[ tokio:: test]
4028+ async fn update_reasoning_effort_updates_collaboration_mode ( ) {
4029+ let mut app = make_test_app ( ) . await ;
4030+ app. chat_widget
4031+ . set_reasoning_effort ( Some ( ReasoningEffortConfig :: Medium ) ) ;
4032+
4033+ app. on_update_reasoning_effort ( Some ( ReasoningEffortConfig :: High ) ) ;
4034+
4035+ assert_eq ! (
4036+ app. chat_widget. current_reasoning_effort( ) ,
4037+ Some ( ReasoningEffortConfig :: High )
4038+ ) ;
4039+ assert_eq ! (
4040+ app. config. model_reasoning_effort,
4041+ Some ( ReasoningEffortConfig :: High )
4042+ ) ;
4043+ }
4044+
4045+ #[ tokio:: test]
4046+ async fn refresh_in_memory_config_from_disk_loads_latest_apps_state ( ) -> Result < ( ) > {
4047+ let mut app = make_test_app ( ) . await ;
4048+ let codex_home = tempdir ( ) ?;
4049+ app. config . codex_home = codex_home. path ( ) . to_path_buf ( ) . abs ( ) ;
4050+ let app_id = "unit_test_refresh_in_memory_config_connector" . to_string ( ) ;
4051+
4052+ assert_eq ! ( app_enabled_in_effective_config( & app. config, & app_id) , None ) ;
4053+
4054+ ConfigEditsBuilder :: new ( & app. config . codex_home )
4055+ . with_edits ( [
4056+ ConfigEdit :: SetPath {
4057+ segments : vec ! [ "apps" . to_string( ) , app_id. clone( ) , "enabled" . to_string( ) ] ,
4058+ value : false . into ( ) ,
4059+ } ,
4060+ ConfigEdit :: SetPath {
4061+ segments : vec ! [
4062+ "apps" . to_string( ) ,
4063+ app_id. clone( ) ,
4064+ "disabled_reason" . to_string( ) ,
4065+ ] ,
4066+ value : "user" . into ( ) ,
4067+ } ,
4068+ ] )
4069+ . apply ( )
4070+ . await
4071+ . expect ( "persist app toggle" ) ;
4072+
4073+ assert_eq ! ( app_enabled_in_effective_config( & app. config, & app_id) , None ) ;
4074+
4075+ app. refresh_in_memory_config_from_disk ( ) . await ?;
4076+
4077+ assert_eq ! (
4078+ app_enabled_in_effective_config( & app. config, & app_id) ,
4079+ Some ( false )
4080+ ) ;
4081+ Ok ( ( ) )
4082+ }
4083+
4084+ #[ tokio:: test]
4085+ async fn refresh_in_memory_config_from_disk_best_effort_keeps_current_config_on_error ( ) -> Result < ( ) >
4086+ {
4087+ let mut app = make_test_app ( ) . await ;
4088+ let codex_home = tempdir ( ) ?;
4089+ app. config . codex_home = codex_home. path ( ) . to_path_buf ( ) . abs ( ) ;
4090+ std:: fs:: write ( codex_home. path ( ) . join ( "config.toml" ) , "[broken" ) ?;
4091+ let original_config = app. config . clone ( ) ;
4092+
4093+ app. refresh_in_memory_config_from_disk_best_effort ( "starting a new thread" )
4094+ . await ;
4095+
4096+ assert_eq ! ( app. config, original_config) ;
4097+ Ok ( ( ) )
4098+ }
4099+
4100+ #[ tokio:: test]
4101+ async fn refresh_in_memory_config_from_disk_uses_active_chat_widget_cwd ( ) -> Result < ( ) > {
4102+ let mut app = make_test_app ( ) . await ;
4103+ let original_cwd = app. config . cwd . clone ( ) ;
4104+ let next_cwd_tmp = tempdir ( ) ?;
4105+ let next_cwd = next_cwd_tmp. path ( ) . to_path_buf ( ) ;
4106+
4107+ app. chat_widget . handle_codex_event ( Event {
4108+ id : String :: new ( ) ,
4109+ msg : EventMsg :: SessionConfigured ( SessionConfiguredEvent {
4110+ session_id : ThreadId :: new ( ) ,
4111+ forked_from_id : None ,
4112+ thread_name : None ,
4113+ model : "gpt-test" . to_string ( ) ,
4114+ model_provider_id : "test-provider" . to_string ( ) ,
4115+ service_tier : None ,
4116+ approval_policy : AskForApproval :: Never ,
4117+ approvals_reviewer : ApprovalsReviewer :: User ,
4118+ sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4119+ permission_profile : None ,
4120+ cwd : next_cwd. clone ( ) . abs ( ) ,
4121+ reasoning_effort : None ,
4122+ history_log_id : 0 ,
4123+ history_entry_count : 0 ,
4124+ initial_messages : None ,
4125+ network_proxy : None ,
4126+ rollout_path : Some ( PathBuf :: new ( ) ) ,
4127+ } ) ,
4128+ } ) ;
4129+
4130+ assert_eq ! ( app. chat_widget. config_ref( ) . cwd. to_path_buf( ) , next_cwd) ;
4131+ assert_eq ! ( app. config. cwd, original_cwd) ;
4132+
4133+ app. refresh_in_memory_config_from_disk ( ) . await ?;
4134+
4135+ assert_eq ! ( app. config. cwd, app. chat_widget. config_ref( ) . cwd) ;
4136+ Ok ( ( ) )
4137+ }
4138+
4139+ #[ tokio:: test]
4140+ async fn rebuild_config_for_resume_or_fallback_uses_current_config_on_same_cwd_error ( ) -> Result < ( ) >
4141+ {
4142+ let mut app = make_test_app ( ) . await ;
4143+ let codex_home = tempdir ( ) ?;
4144+ app. config . codex_home = codex_home. path ( ) . to_path_buf ( ) . abs ( ) ;
4145+ std:: fs:: write ( codex_home. path ( ) . join ( "config.toml" ) , "[broken" ) ?;
4146+ let current_config = app. config . clone ( ) ;
4147+ let current_cwd = current_config. cwd . clone ( ) ;
4148+
4149+ let resume_config = app
4150+ . rebuild_config_for_resume_or_fallback ( & current_cwd, current_cwd. to_path_buf ( ) )
4151+ . await ?;
4152+
4153+ assert_eq ! ( resume_config, current_config) ;
4154+ Ok ( ( ) )
4155+ }
4156+
4157+ #[ tokio:: test]
4158+ async fn rebuild_config_for_resume_or_fallback_errors_when_cwd_changes ( ) -> Result < ( ) > {
4159+ let mut app = make_test_app ( ) . await ;
4160+ let codex_home = tempdir ( ) ?;
4161+ app. config . codex_home = codex_home. path ( ) . to_path_buf ( ) . abs ( ) ;
4162+ std:: fs:: write ( codex_home. path ( ) . join ( "config.toml" ) , "[broken" ) ?;
4163+ let current_cwd = app. config . cwd . clone ( ) ;
4164+ let next_cwd_tmp = tempdir ( ) ?;
4165+ let next_cwd = next_cwd_tmp. path ( ) . to_path_buf ( ) ;
4166+
4167+ let result = app
4168+ . rebuild_config_for_resume_or_fallback ( & current_cwd, next_cwd)
4169+ . await ;
4170+
4171+ assert ! ( result. is_err( ) ) ;
4172+ Ok ( ( ) )
4173+ }
4174+
4175+ #[ tokio:: test]
4176+ async fn sync_tui_theme_selection_updates_chat_widget_config_copy ( ) {
4177+ let mut app = make_test_app ( ) . await ;
4178+
4179+ app. sync_tui_theme_selection ( "dracula" . to_string ( ) ) ;
4180+
4181+ assert_eq ! ( app. config. tui_theme. as_deref( ) , Some ( "dracula" ) ) ;
4182+ assert_eq ! (
4183+ app. chat_widget. config_ref( ) . tui_theme. as_deref( ) ,
4184+ Some ( "dracula" )
4185+ ) ;
4186+ }
4187+
40264188#[ tokio:: test]
40274189async fn fresh_session_config_uses_current_service_tier ( ) {
40284190 let mut app = make_test_app ( ) . await ;
@@ -4071,6 +4233,7 @@ async fn backtrack_selection_with_duplicate_history_targets_unique_turn() {
40714233 approval_policy : AskForApproval :: Never ,
40724234 approvals_reviewer : ApprovalsReviewer :: User ,
40734235 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4236+ permission_profile : None ,
40744237 cwd : test_path_buf ( "/home/user/project" ) . abs ( ) ,
40754238 reasoning_effort : None ,
40764239 history_log_id : 0 ,
@@ -4134,6 +4297,7 @@ async fn backtrack_selection_with_duplicate_history_targets_unique_turn() {
41344297 approval_policy : AskForApproval :: Never ,
41354298 approvals_reviewer : ApprovalsReviewer :: User ,
41364299 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4300+ permission_profile : None ,
41374301 cwd : test_path_buf ( "/home/user/project" ) . abs ( ) ,
41384302 reasoning_effort : None ,
41394303 history_log_id : 0 ,
@@ -4227,6 +4391,7 @@ async fn backtrack_resubmit_preserves_data_image_urls_in_user_turn() {
42274391 approval_policy : AskForApproval :: Never ,
42284392 approvals_reviewer : ApprovalsReviewer :: User ,
42294393 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4394+ permission_profile : None ,
42304395 cwd : test_path_buf ( "/home/user/project" ) . abs ( ) ,
42314396 reasoning_effort : None ,
42324397 history_log_id : 0 ,
@@ -4610,6 +4775,7 @@ async fn new_session_requests_shutdown_for_previous_conversation() {
46104775 approval_policy : AskForApproval :: Never ,
46114776 approvals_reviewer : ApprovalsReviewer :: User ,
46124777 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4778+ permission_profile : None ,
46134779 cwd : test_path_buf ( "/home/user/project" ) . abs ( ) ,
46144780 reasoning_effort : None ,
46154781 history_log_id : 0 ,
@@ -4722,6 +4888,7 @@ async fn clear_only_ui_reset_preserves_chat_session_state() {
47224888 approval_policy : AskForApproval :: Never ,
47234889 approvals_reviewer : ApprovalsReviewer :: User ,
47244890 sandbox_policy : SandboxPolicy :: new_read_only_policy ( ) ,
4891+ permission_profile : None ,
47254892 cwd : test_path_buf ( "/tmp/project" ) . abs ( ) ,
47264893 reasoning_effort : None ,
47274894 history_log_id : 0 ,
0 commit comments