mirror of
https://github.com/openai/codex.git
synced 2026-11-15 14:52:36 +00:00
Snapshot resolved settings for each model step (#40651)
## Why Thread settings can change while a turn is running, and delegated review or compaction steps can select a different model. Each request needs a consistent set of settings resolved against the model that will execute it. ## What changed - Capture immutable resolved settings for each model step, including model metadata, reasoning options, service tier, approvals, and personality. - Keep in-flight steps on their captured settings while applying thread updates to subsequent work. - Resolve inherited reasoning summaries and filter service tiers against the selected model and feature configuration for review and compaction steps. ## Testing Added coverage for settings updates during paused turns, model changes, previous-model compaction, review-model defaults, and service-tier filtering. GitOrigin-RevId: fca4b3b305379f1bf26a5cac75ee0dd1747ac1f6
This commit is contained in:
1 parent
ba6cf9c692
commit
68301fa45f
68 files changed
+1393
-516
No files matched your search
@@ -272,8 +272,8 @@ pub(crate) async fn run_turn(
|
||||
sess.merge_connector_selection(explicitly_enabled_connectors.clone())
|
||||
.await;
|
||||
sess.set_previous_turn_settings(Some(PreviousTurnSettings {
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
comp_hash: turn_context.model_info.comp_hash.clone(),
|
||||
model: turn_context.model_info().slug.clone(),
|
||||
comp_hash: turn_context.model_info().comp_hash.clone(),
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
}))
|
||||
.await;
|
||||
@@ -372,7 +372,7 @@ pub(crate) async fn run_turn(
|
||||
let sampling_request_input: Vec<ResponseItem> = async {
|
||||
sess.clone_history()
|
||||
.await
|
||||
.for_prompt(&step_context.model_info.input_modalities)
|
||||
.for_prompt(&step_context.settings.model_info.input_modalities)
|
||||
}
|
||||
.instrument(trace_span!("run_turn.prepare_sampling_request_input"))
|
||||
.await;
|
||||
@@ -782,7 +782,7 @@ async fn build_skills_and_plugins(
|
||||
}
|
||||
|
||||
let tracking = build_track_events_context(
|
||||
turn_context.model_info.slug.clone(),
|
||||
turn_context.model_info().slug.clone(),
|
||||
sess.thread_id.to_string(),
|
||||
turn_context.sub_id.clone(),
|
||||
turn_context.originator.clone(),
|
||||
@@ -999,13 +999,13 @@ async fn track_turn_resolved_config_analytics(
|
||||
submission_type: None,
|
||||
ephemeral: thread_config.ephemeral,
|
||||
session_source: thread_config.session_source,
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
model: turn_context.model_info().slug.clone(),
|
||||
model_provider: turn_context.config.model_provider_id.clone(),
|
||||
permission_profile: turn_context.permission_profile(),
|
||||
#[allow(deprecated)]
|
||||
permission_profile_cwd: turn_context.cwd.to_path_buf(),
|
||||
reasoning_effort: turn_context.reasoning_effort.clone(),
|
||||
reasoning_summary: Some(turn_context.reasoning_summary),
|
||||
reasoning_effort: turn_context.reasoning_effort().cloned(),
|
||||
reasoning_summary: Some(turn_context.reasoning_summary()),
|
||||
service_tier: turn_context
|
||||
.config
|
||||
.service_tier
|
||||
@@ -1014,8 +1014,8 @@ async fn track_turn_resolved_config_analytics(
|
||||
approval_policy: turn_context.approval_policy(),
|
||||
approvals_reviewer: turn_context.config.approvals_reviewer,
|
||||
sandbox_network_access: turn_context.network_sandbox_policy().is_enabled(),
|
||||
collaboration_mode: turn_context.mode,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: turn_context.mode(),
|
||||
personality: turn_context.personality(),
|
||||
workspace_kind: turn_context.turn_metadata_state.workspace_kind(),
|
||||
is_first_turn,
|
||||
});
|
||||
@@ -1077,7 +1077,7 @@ async fn capture_current_model_fallback_step_context(
|
||||
.is_some_and(codex_login::AuthManager::current_auth_uses_codex_backend);
|
||||
if !uses_codex_backend
|
||||
|| !turn_context.provider.info().is_openai()
|
||||
|| previous_model == turn_context.model_info.slug
|
||||
|| previous_model == turn_context.model_info().slug
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -1101,7 +1101,7 @@ async fn maybe_run_previous_model_inline_compact(
|
||||
};
|
||||
let should_compact_for_comp_hash_change = comp_hash_changed(
|
||||
previous_turn_settings.comp_hash.as_deref(),
|
||||
turn_context.model_info.comp_hash.as_deref(),
|
||||
turn_context.model_info().comp_hash.as_deref(),
|
||||
);
|
||||
let previous_model = previous_turn_settings.model;
|
||||
let previous_model_turn_context = Arc::new(
|
||||
@@ -1147,7 +1147,7 @@ async fn maybe_run_previous_model_inline_compact(
|
||||
{
|
||||
AutoCompactTokenLimitScope::Total => {
|
||||
let new_auto_compact_limit = turn_context
|
||||
.model_info
|
||||
.model_info()
|
||||
.auto_compact_token_limit()
|
||||
.unwrap_or(i64::MAX);
|
||||
active_context_tokens > new_auto_compact_limit
|
||||
@@ -1156,7 +1156,7 @@ async fn maybe_run_previous_model_inline_compact(
|
||||
AutoCompactTokenLimitScope::BodyAfterPrefix => active_context_tokens >= new_context_window,
|
||||
};
|
||||
let should_run = previous_model_limit_reached
|
||||
&& previous_model_turn_context.model_info.slug != turn_context.model_info.slug
|
||||
&& previous_model_turn_context.model_info().slug != turn_context.model_info().slug
|
||||
&& old_context_window > new_context_window;
|
||||
if should_run {
|
||||
let step_context = sess
|
||||
@@ -1346,7 +1346,7 @@ pub(crate) fn build_prompt(
|
||||
skip_all,
|
||||
fields(
|
||||
turn_id = %step_context.turn.sub_id,
|
||||
model = %step_context.model_info.slug,
|
||||
model = %step_context.settings.model_info.slug,
|
||||
cwd = %step_context.turn.cwd.display()
|
||||
)
|
||||
)]
|
||||
@@ -1384,7 +1384,7 @@ async fn run_sampling_request(
|
||||
} else {
|
||||
sess.clone_history()
|
||||
.await
|
||||
.for_prompt(&step_context.model_info.input_modalities)
|
||||
.for_prompt(&step_context.settings.model_info.input_modalities)
|
||||
};
|
||||
let mut prompt_input = prompt_input;
|
||||
if let Some(executed_tool_calls) = sess.services.executed_tool_calls.as_ref()
|
||||
@@ -1500,7 +1500,7 @@ pub(crate) async fn prepare_tool_recommendations(
|
||||
skip_all,
|
||||
fields(
|
||||
turn_id = %turn_context.sub_id,
|
||||
model = %turn_context.model_info.slug,
|
||||
model = %turn_context.model_info().slug,
|
||||
apps_enabled = turn_context.apps_enabled()
|
||||
)
|
||||
)]
|
||||
@@ -2186,7 +2186,7 @@ fn assign_missing_streamed_response_item_id(
|
||||
skip_all,
|
||||
fields(
|
||||
turn_id = %step_context.turn.sub_id,
|
||||
model = %step_context.model_info.slug
|
||||
model = %step_context.settings.model_info.slug
|
||||
)
|
||||
)]
|
||||
async fn try_run_sampling_request(
|
||||
@@ -2202,16 +2202,16 @@ async fn try_run_sampling_request(
|
||||
) -> CodexResult<SamplingRequestResult> {
|
||||
let turn_context = Arc::clone(&step_context.turn);
|
||||
feedback_tags!(
|
||||
model = step_context.model_info.slug.clone(),
|
||||
model = step_context.settings.model_info.slug.clone(),
|
||||
approval_policy = turn_context.approval_policy(),
|
||||
sandbox_policy = &turn_context.sandbox_policy(),
|
||||
effort = step_context.reasoning_effort,
|
||||
effort = step_context.settings.reasoning_effort(),
|
||||
auth_mode = sess.services.auth_manager.auth_mode(),
|
||||
features = sess.features.enabled_features(),
|
||||
);
|
||||
let inference_trace = sess.services.rollout_thread_trace.inference_trace_context(
|
||||
turn_context.sub_id.as_str(),
|
||||
step_context.model_info.slug.as_str(),
|
||||
step_context.settings.model_info.slug.as_str(),
|
||||
turn_context.provider.info().name.as_str(),
|
||||
);
|
||||
let sampling_timing_guard = turn_context.turn_timing_state.begin_sampling();
|
||||
@@ -2223,11 +2223,11 @@ async fn try_run_sampling_request(
|
||||
let mut stream = client_session
|
||||
.stream(
|
||||
prompt,
|
||||
&step_context.model_info,
|
||||
&step_context.settings.model_info,
|
||||
&step_context.session_telemetry,
|
||||
step_context.reasoning_effort.clone(),
|
||||
step_context.reasoning_summary,
|
||||
step_context.service_tier.clone(),
|
||||
step_context.settings.reasoning_effort().cloned(),
|
||||
step_context.settings.reasoning_summary,
|
||||
step_context.settings.service_tier.clone(),
|
||||
responses_metadata,
|
||||
&inference_trace,
|
||||
)
|
||||
@@ -2248,12 +2248,16 @@ async fn try_run_sampling_request(
|
||||
const MAX_ANALYTICS_TOOL_CALL_IDS_PER_RESPONSE: usize = 256;
|
||||
let mut analytics_tool_call_ids = Vec::new();
|
||||
let reasoning_effort = step_context
|
||||
.reasoning_effort
|
||||
.clone()
|
||||
.or_else(|| step_context.model_info.default_reasoning_level.clone())
|
||||
.map(|effort| effort.to_string())
|
||||
.settings
|
||||
.reasoning_effort()
|
||||
.or(step_context
|
||||
.settings
|
||||
.model_info
|
||||
.default_reasoning_level
|
||||
.as_ref())
|
||||
.map(std::string::ToString::to_string)
|
||||
.unwrap_or_else(|| "default".to_string());
|
||||
let plan_mode = turn_context.mode == ModeKind::Plan;
|
||||
let plan_mode = turn_context.mode() == ModeKind::Plan;
|
||||
let mut assistant_message_stream_parsers = AssistantMessageStreamParsers::new(plan_mode);
|
||||
let mut plan_mode_state = plan_mode.then(|| PlanModeStreamState::new(&turn_context.sub_id));
|
||||
let defer_streamed_turn_items_for_contributors =
|
||||
@@ -2499,7 +2503,7 @@ async fn try_run_sampling_request(
|
||||
.server_model_warning_emitted
|
||||
.load(Ordering::Relaxed)
|
||||
&& sess
|
||||
.maybe_warn_on_server_model_mismatch(&turn_context, server_model)
|
||||
.maybe_warn_on_server_model_mismatch(&step_context, server_model)
|
||||
.await
|
||||
{
|
||||
turn_context
|
||||
@@ -2524,7 +2528,7 @@ async fn try_run_sampling_request(
|
||||
sess.send_event(
|
||||
&turn_context,
|
||||
EventMsg::SafetyBuffering(SafetyBufferingEvent {
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
model: step_context.settings.model_info.slug.clone(),
|
||||
use_cases: buffering.use_cases,
|
||||
reasons: buffering.reasons,
|
||||
show_buffering_ui: buffering.show_buffering_ui,
|
||||
|
||||
Reference in new issue
Block a user