mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
Preserve thread settings for goal-first and forked threads (#34469)
## Why Goal-first and forked threads could create rollouts without recording their effective thread settings. Resuming those threads after a restart could then use current configuration instead of the settings selected when the thread was created. ## What changed - Persist a `thread_settings_applied` item when a goal first materializes a rollout, including a follow-up snapshot if settings changed concurrently. - Append each fork's effective settings after its copied history so they take precedence over inherited settings during resume. - Centralize conversion from `ThreadConfigSnapshot` to `ThreadSettingsSnapshot`. ## Testing Added coverage that restarts the app server and verifies goal-first and forked threads retain their respective `approvals_reviewer` settings. GitOrigin-RevId: 6cb9aaae73bbe9ca432831cff7e826f95ffd6d01
This commit is contained in:
1 parent
9970cd706f
commit
1836ae0612
7 files changed
+230
-30
No files matched your search
@@ -34,6 +34,7 @@ use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::Submission;
|
||||
use codex_protocol::protocol::ThreadHistoryMode;
|
||||
use codex_protocol::protocol::ThreadMemoryMode;
|
||||
use codex_protocol::protocol::ThreadSettingsSnapshot;
|
||||
use codex_protocol::protocol::ThreadSource;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
use codex_protocol::protocol::TurnEnvironmentSelection;
|
||||
@@ -138,6 +139,24 @@ impl ThreadConfigSnapshot {
|
||||
self.cwd().as_path(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn into_thread_settings_snapshot(self) -> ThreadSettingsSnapshot {
|
||||
let cwd = self.cwd().clone();
|
||||
ThreadSettingsSnapshot {
|
||||
model: self.model,
|
||||
model_provider_id: self.model_provider_id,
|
||||
service_tier: self.service_tier,
|
||||
approval_policy: self.approval_policy,
|
||||
approvals_reviewer: self.approvals_reviewer,
|
||||
permission_profile: self.permission_profile,
|
||||
active_permission_profile: self.active_permission_profile,
|
||||
cwd,
|
||||
reasoning_effort: self.reasoning_effort,
|
||||
reasoning_summary: self.reasoning_summary,
|
||||
personality: self.personality,
|
||||
collaboration_mode: self.collaboration_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Thread settings overrides that app-server validates before starting a turn.
|
||||
|
||||
@@ -43,7 +43,6 @@ use codex_protocol::protocol::ThreadMemoryMode;
|
||||
use codex_protocol::protocol::ThreadRolledBackEvent;
|
||||
use codex_protocol::protocol::ThreadSettingsAppliedEvent;
|
||||
use codex_protocol::protocol::ThreadSettingsOverrides;
|
||||
use codex_protocol::protocol::ThreadSettingsSnapshot;
|
||||
use codex_protocol::protocol::TurnAbortReason;
|
||||
use codex_protocol::protocol::WarningEvent;
|
||||
use codex_protocol::request_permissions::RequestPermissionsResponse;
|
||||
@@ -165,27 +164,13 @@ async fn thread_settings_update(
|
||||
}
|
||||
}
|
||||
|
||||
async fn thread_settings_applied_event(sess: &Session) -> EventMsg {
|
||||
pub(super) async fn thread_settings_applied_event(sess: &Session) -> EventMsg {
|
||||
let snapshot = {
|
||||
let state = sess.state.lock().await;
|
||||
state.session_configuration.thread_config_snapshot()
|
||||
};
|
||||
let cwd = snapshot.cwd().clone();
|
||||
EventMsg::ThreadSettingsApplied(ThreadSettingsAppliedEvent {
|
||||
thread_settings: ThreadSettingsSnapshot {
|
||||
model: snapshot.model,
|
||||
model_provider_id: snapshot.model_provider_id,
|
||||
service_tier: snapshot.service_tier,
|
||||
approval_policy: snapshot.approval_policy,
|
||||
approvals_reviewer: snapshot.approvals_reviewer,
|
||||
permission_profile: snapshot.permission_profile,
|
||||
active_permission_profile: snapshot.active_permission_profile,
|
||||
cwd,
|
||||
reasoning_effort: snapshot.reasoning_effort,
|
||||
reasoning_summary: snapshot.reasoning_summary,
|
||||
personality: snapshot.personality,
|
||||
collaboration_mode: snapshot.collaboration_mode,
|
||||
},
|
||||
thread_settings: snapshot.into_thread_settings_snapshot(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1336,9 +1336,16 @@ impl Session {
|
||||
state.set_token_info(Some(info));
|
||||
}
|
||||
|
||||
// Paginated subagents persist inherited model context while creating the live
|
||||
// thread so the copied prefix is not observed as child-owned metadata.
|
||||
if !rollout_items.is_empty() && !is_paginated_subagent {
|
||||
let thread_settings_applied =
|
||||
RolloutItem::EventMsg(handlers::thread_settings_applied_event(self).await);
|
||||
if is_paginated_subagent {
|
||||
// Paginated subagents persist inherited model context while creating the live
|
||||
// thread so the copied prefix is not observed as child-owned metadata.
|
||||
self.persist_rollout_items(&[thread_settings_applied]).await;
|
||||
} else {
|
||||
// Keep the copied prefix and the child's effective settings in one append so a
|
||||
// cold resume cannot observe inherited settings as the child's latest value.
|
||||
rollout_items.push(thread_settings_applied);
|
||||
self.persist_rollout_items(&rollout_items).await;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user