@@ -215,7 +215,7 @@ pub(crate) struct CodexMessageProcessor {
215215 outgoing : Arc < OutgoingMessageSender > ,
216216 codex_linux_sandbox_exe : Option < PathBuf > ,
217217 config : Arc < Config > ,
218- startup_cli_overrides : Vec < ( String , TomlValue ) > ,
218+ cli_overrides : Vec < ( String , TomlValue ) > ,
219219 conversation_listeners : HashMap < Uuid , oneshot:: Sender < ( ) > > ,
220220 active_login : Arc < Mutex < Option < ActiveLogin > > > ,
221221 // Queue of pending interrupt requests per conversation. We reply when TurnAborted arrives.
@@ -262,7 +262,7 @@ impl CodexMessageProcessor {
262262 outgoing : Arc < OutgoingMessageSender > ,
263263 codex_linux_sandbox_exe : Option < PathBuf > ,
264264 config : Arc < Config > ,
265- startup_cli_overrides : Vec < ( String , TomlValue ) > ,
265+ cli_overrides : Vec < ( String , TomlValue ) > ,
266266 feedback : CodexFeedback ,
267267 ) -> Self {
268268 Self {
@@ -271,7 +271,7 @@ impl CodexMessageProcessor {
271271 outgoing,
272272 codex_linux_sandbox_exe,
273273 config,
274- startup_cli_overrides ,
274+ cli_overrides ,
275275 conversation_listeners : HashMap :: new ( ) ,
276276 active_login : Arc :: new ( Mutex :: new ( None ) ) ,
277277 pending_interrupts : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
@@ -282,7 +282,7 @@ impl CodexMessageProcessor {
282282 }
283283
284284 async fn load_latest_config ( & self ) -> Result < Config , JSONRPCErrorError > {
285- Config :: load_with_cli_overrides ( self . startup_cli_overrides . clone ( ) )
285+ Config :: load_with_cli_overrides ( self . cli_overrides . clone ( ) )
286286 . await
287287 . map_err ( |err| JSONRPCErrorError {
288288 code : INTERNAL_ERROR_CODE ,
@@ -1246,14 +1246,14 @@ impl CodexMessageProcessor {
12461246 cwd,
12471247 approval_policy,
12481248 sandbox : sandbox_mode,
1249- config : request_config_overrides ,
1249+ config : request_overrides ,
12501250 base_instructions,
12511251 developer_instructions,
12521252 compact_prompt,
12531253 include_apply_patch_tool,
12541254 } = params;
12551255
1256- let harness_overrides = ConfigOverrides {
1256+ let forced_overrides = ConfigOverrides {
12571257 model,
12581258 config_profile : profile,
12591259 cwd : cwd. clone ( ) . map ( PathBuf :: from) ,
@@ -1270,18 +1270,18 @@ impl CodexMessageProcessor {
12701270
12711271 // Persist windows sandbox feature.
12721272 // TODO: persist default config in general.
1273- let mut request_config_overrides = request_config_overrides . unwrap_or_default ( ) ;
1273+ let mut request_overrides = request_overrides . unwrap_or_default ( ) ;
12741274 if cfg ! ( windows) && self . config . features . enabled ( Feature :: WindowsSandbox ) {
1275- request_config_overrides . insert (
1275+ request_overrides . insert (
12761276 "features.experimental_windows_sandbox" . to_string ( ) ,
12771277 serde_json:: json!( true ) ,
12781278 ) ;
12791279 }
12801280
12811281 let config = match derive_config_from_params (
1282- & self . startup_cli_overrides ,
1283- harness_overrides ,
1284- Some ( request_config_overrides ) ,
1282+ & self . cli_overrides ,
1283+ forced_overrides ,
1284+ Some ( request_overrides ) ,
12851285 )
12861286 . await
12871287 {
@@ -1324,7 +1324,7 @@ impl CodexMessageProcessor {
13241324 }
13251325
13261326 async fn thread_start ( & mut self , request_id : RequestId , params : ThreadStartParams ) {
1327- let harness_overrides = self . build_thread_config_overrides (
1327+ let forced_overrides = self . build_thread_config_overrides (
13281328 params. model ,
13291329 params. model_provider ,
13301330 params. cwd ,
@@ -1334,24 +1334,21 @@ impl CodexMessageProcessor {
13341334 params. developer_instructions ,
13351335 ) ;
13361336
1337- let config = match derive_config_from_params (
1338- & self . startup_cli_overrides ,
1339- harness_overrides,
1340- params. config ,
1341- )
1342- . await
1343- {
1344- Ok ( config) => config,
1345- Err ( err) => {
1346- let error = JSONRPCErrorError {
1347- code : INVALID_REQUEST_ERROR_CODE ,
1348- message : format ! ( "error deriving config: {err}" ) ,
1349- data : None ,
1350- } ;
1351- self . outgoing . send_error ( request_id, error) . await ;
1352- return ;
1353- }
1354- } ;
1337+ let config =
1338+ match derive_config_from_params ( & self . cli_overrides , forced_overrides, params. config )
1339+ . await
1340+ {
1341+ Ok ( config) => config,
1342+ Err ( err) => {
1343+ let error = JSONRPCErrorError {
1344+ code : INVALID_REQUEST_ERROR_CODE ,
1345+ message : format ! ( "error deriving config: {err}" ) ,
1346+ data : None ,
1347+ } ;
1348+ self . outgoing . send_error ( request_id, error) . await ;
1349+ return ;
1350+ }
1351+ } ;
13551352
13561353 match self . conversation_manager . new_conversation ( config) . await {
13571354 Ok ( new_conv) => {
@@ -1555,7 +1552,7 @@ impl CodexMessageProcessor {
15551552 cwd,
15561553 approval_policy,
15571554 sandbox,
1558- config : request_config_overrides ,
1555+ config : request_overrides ,
15591556 base_instructions,
15601557 developer_instructions,
15611558 } = params;
@@ -1565,12 +1562,12 @@ impl CodexMessageProcessor {
15651562 || cwd. is_some ( )
15661563 || approval_policy. is_some ( )
15671564 || sandbox. is_some ( )
1568- || request_config_overrides . is_some ( )
1565+ || request_overrides . is_some ( )
15691566 || base_instructions. is_some ( )
15701567 || developer_instructions. is_some ( ) ;
15711568
15721569 let config = if overrides_requested {
1573- let harness_overrides = self . build_thread_config_overrides (
1570+ let forced_overrides = self . build_thread_config_overrides (
15741571 model,
15751572 model_provider,
15761573 cwd,
@@ -1580,9 +1577,9 @@ impl CodexMessageProcessor {
15801577 developer_instructions,
15811578 ) ;
15821579 match derive_config_from_params (
1583- & self . startup_cli_overrides ,
1584- harness_overrides ,
1585- request_config_overrides ,
1580+ & self . cli_overrides ,
1581+ forced_overrides ,
1582+ request_overrides ,
15861583 )
15871584 . await
15881585 {
@@ -2215,23 +2212,23 @@ impl CodexMessageProcessor {
22152212 cwd,
22162213 approval_policy,
22172214 sandbox : sandbox_mode,
2218- config : request_config_overrides ,
2215+ config : request_overrides ,
22192216 base_instructions,
22202217 developer_instructions,
22212218 compact_prompt,
22222219 include_apply_patch_tool,
22232220 } = overrides;
22242221
22252222 // Persist windows sandbox feature.
2226- let mut request_config_overrides = request_config_overrides . unwrap_or_default ( ) ;
2223+ let mut request_overrides = request_overrides . unwrap_or_default ( ) ;
22272224 if cfg ! ( windows) && self . config . features . enabled ( Feature :: WindowsSandbox ) {
2228- request_config_overrides . insert (
2225+ request_overrides . insert (
22292226 "features.experimental_windows_sandbox" . to_string ( ) ,
22302227 serde_json:: json!( true ) ,
22312228 ) ;
22322229 }
22332230
2234- let harness_overrides = ConfigOverrides {
2231+ let forced_overrides = ConfigOverrides {
22352232 model,
22362233 config_profile : profile,
22372234 cwd : cwd. map ( PathBuf :: from) ,
@@ -2247,9 +2244,9 @@ impl CodexMessageProcessor {
22472244 } ;
22482245
22492246 derive_config_from_params (
2250- & self . startup_cli_overrides ,
2251- harness_overrides ,
2252- Some ( request_config_overrides ) ,
2247+ & self . cli_overrides ,
2248+ forced_overrides ,
2249+ Some ( request_overrides ) ,
22532250 )
22542251 . await
22552252 }
@@ -3366,22 +3363,31 @@ fn errors_to_info(
33663363 . collect ( )
33673364}
33683365
3366+ /// Derive the effective [`Config`] by layering three override sources.
3367+ ///
3368+ /// Precedence (highest to lowest):
3369+ /// - `forced_overrides`: strongly-typed "forced" values from the harness/app-server (e.g. `cwd`,
3370+ /// sandbox/approval policy, model/provider, instructions).
3371+ /// - `request_overrides`: per-request dotted-path overrides (`params.config`), converted JSON->TOML;
3372+ /// applied after `cli_overrides`.
3373+ /// - `cli_overrides`: process-wide startup `--config` flags.
33693374async fn derive_config_from_params (
3370- startup_cli_overrides : & [ ( String , TomlValue ) ] ,
3371- harness_overrides : ConfigOverrides ,
3372- request_config_overrides : Option < HashMap < String , serde_json:: Value > > ,
3375+ cli_overrides : & [ ( String , TomlValue ) ] ,
3376+ forced_overrides : ConfigOverrides ,
3377+ request_overrides : Option < HashMap < String , serde_json:: Value > > ,
33733378) -> std:: io:: Result < Config > {
3374- // Apply the app server's startup `--config` overrides, then apply request-scoped
3375- // overrides with higher precedence.
3376- let mut merged_cli_overrides: Vec < ( String , TomlValue ) > = startup_cli_overrides. to_vec ( ) ;
3377- merged_cli_overrides. extend (
3378- request_config_overrides
3379- . unwrap_or_default ( )
3380- . into_iter ( )
3381- . map ( |( k, v) | ( k, json_to_toml ( v) ) ) ,
3382- ) ;
3379+ let merged_cli_overrides = cli_overrides
3380+ . iter ( )
3381+ . cloned ( )
3382+ . chain (
3383+ request_overrides
3384+ . unwrap_or_default ( )
3385+ . into_iter ( )
3386+ . map ( |( k, v) | ( k, json_to_toml ( v) ) ) ,
3387+ )
3388+ . collect :: < Vec < _ > > ( ) ;
33833389
3384- Config :: load_with_cli_overrides_and_harness_overrides ( merged_cli_overrides, harness_overrides )
3390+ Config :: load_with_cli_overrides_and_harness_overrides ( merged_cli_overrides, forced_overrides )
33853391 . await
33863392}
33873393
0 commit comments