mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Keep settings operations bound to their committed snapshot (#40645)
## Why Post-commit work can overlap with another settings write. Reading the session again afterward could make a settings operation report or use the later state instead of the state that it committed. ## What changed - Return the committed configuration and `ThreadSettingsSnapshot` from session settings updates. - Use that commit result when creating a turn and emitting `ThreadSettingsApplied`, while retaining current-state snapshots for synthesized fork history. - Route turn-start updates through the shared settings update path. ## Testing Add coverage for standalone and turn-start updates that pause after committing, restore different settings concurrently, and verify that each operation keeps its original configuration and notification snapshot. GitOrigin-RevId: cee5be9536d2840170893e6eb0c64cd039fb0a96
This commit is contained in:
1 parent
a95391160a
commit
4e883ce36e
10 files changed
+279
-91
No files matched your search
@@ -743,59 +743,15 @@ impl Session {
|
||||
&self,
|
||||
sub_id: String,
|
||||
updates: SessionSettingsUpdate,
|
||||
) -> CodexResult<Arc<TurnContext>> {
|
||||
let notify_config_contributors = !self.services.extensions.config_contributors().is_empty();
|
||||
let update_result: CodexResult<_> = {
|
||||
let mut state = self.state.lock().await;
|
||||
match self.apply_session_settings(&state.session_configuration, &updates) {
|
||||
Ok(next) => {
|
||||
let mcp_inputs_changed =
|
||||
self.mcp_inputs_differ(&state.session_configuration, &next, &updates);
|
||||
if mcp_inputs_changed {
|
||||
self.mark_mcp_runtime_dirty();
|
||||
}
|
||||
let previous_permission_profile =
|
||||
state.session_configuration.permission_profile();
|
||||
let next_permission_profile = next.permission_profile();
|
||||
let permission_profile_changed =
|
||||
previous_permission_profile != next_permission_profile;
|
||||
let previous_config = notify_config_contributors
|
||||
.then(|| self.build_effective_session_config(&state.session_configuration));
|
||||
let environment_config = next.inferred_environment_config();
|
||||
if let Some(environments) = &updates.environments {
|
||||
self.services
|
||||
.turn_environments
|
||||
.update_selections(&environments.environments, &environment_config);
|
||||
} else if state.session_configuration.inferred_environment_config()
|
||||
!= environment_config
|
||||
{
|
||||
self.services
|
||||
.turn_environments
|
||||
.update_thread_config(&environment_config);
|
||||
}
|
||||
state.session_configuration = next.clone();
|
||||
let new_config = notify_config_contributors
|
||||
.then(|| self.build_effective_session_config(&state.session_configuration));
|
||||
Ok((
|
||||
next,
|
||||
mcp_inputs_changed,
|
||||
permission_profile_changed,
|
||||
previous_config,
|
||||
new_config,
|
||||
))
|
||||
}
|
||||
Err(err) => Err(CodexErr::InvalidRequest(err.to_string())),
|
||||
}
|
||||
};
|
||||
|
||||
let (
|
||||
mut session_configuration,
|
||||
mcp_inputs_changed,
|
||||
permission_profile_changed,
|
||||
previous_config,
|
||||
new_config,
|
||||
) = match update_result {
|
||||
Ok(update) => update,
|
||||
) -> CodexResult<(Arc<TurnContext>, ThreadSettingsSnapshot)> {
|
||||
let final_output_json_schema = updates.final_output_json_schema.clone();
|
||||
let service_tier_for_turn = updates.service_tier_for_turn.clone();
|
||||
let update_result = self
|
||||
.update_settings(updates)
|
||||
.await
|
||||
.map_err(|err| CodexErr::InvalidRequest(err.to_string()));
|
||||
let commit = match update_result {
|
||||
Ok(commit) => commit,
|
||||
Err(err) => {
|
||||
let message = err.to_string();
|
||||
self.send_event_raw(Event {
|
||||
@@ -809,26 +765,15 @@ impl Session {
|
||||
return Err(CodexErr::InvalidRequest(message));
|
||||
}
|
||||
};
|
||||
self.emit_config_changed_contributors(previous_config.as_ref(), new_config.as_ref());
|
||||
if mcp_inputs_changed {
|
||||
self.schedule_mcp_prewarm();
|
||||
}
|
||||
|
||||
if permission_profile_changed {
|
||||
self.refresh_managed_network_proxy_for_current_permission_profile()
|
||||
.await;
|
||||
}
|
||||
let mut configuration = commit.configuration;
|
||||
// Apply the override only to the turn's copy, after persisting thread settings.
|
||||
if let Some(service_tier) = updates.service_tier_for_turn {
|
||||
session_configuration.service_tier = Some(service_tier);
|
||||
if let Some(service_tier) = service_tier_for_turn {
|
||||
configuration.service_tier = Some(service_tier);
|
||||
}
|
||||
Ok(self
|
||||
.new_turn_from_configuration(
|
||||
sub_id,
|
||||
session_configuration,
|
||||
updates.final_output_json_schema,
|
||||
)
|
||||
.await)
|
||||
let turn_context = self
|
||||
.new_turn_from_configuration(sub_id, configuration, final_output_json_schema)
|
||||
.await;
|
||||
Ok((turn_context, commit.snapshot))
|
||||
}
|
||||
|
||||
async fn new_turn_from_configuration(
|
||||
|
||||
Reference in new issue
Block a user