mirror of
https://github.com/openai/codex.git
synced 2026-11-09 00:39:32 +00:00
Use captured step model settings for extension context (#44202)
## Why Model switches within a turn can leave extension context using stale model metadata. Skill catalogs, context windows, and metric attribution need to match the model captured for each sampling step. ## What changed - Pass captured model metadata and step-specific telemetry to world-state contributors. - Use that metadata for skill catalog budgets and usage instructions, preserving configured budget overrides. - Supply the captured model's usable context window to turn-context contributors, including when rebuilding context. ## Testing Add regression coverage for model switches during skill discovery, catalog budgets and metric attribution, and extension context windows after `new_context` and retained-step context rebuilds. GitOrigin-RevId: c51b40b739a380b9767a54ea8c8ee6de45bf01c8
This commit is contained in:
1 parent
b4507997e0
commit
8ff4aa8ee4
9 files changed
+447
-99
No files matched your search
@@ -3964,7 +3964,7 @@ impl Session {
|
||||
session_store: &self.services.session_extension_data,
|
||||
thread_store: &self.services.thread_extension_data,
|
||||
turn_store: turn_context.extension_data.as_ref(),
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
model_context_window: step_context.settings.model_info.usable_context_window(),
|
||||
})
|
||||
.await
|
||||
{
|
||||
@@ -4066,7 +4066,7 @@ impl Session {
|
||||
session_store: &self.services.session_extension_data,
|
||||
thread_store: &self.services.thread_extension_data,
|
||||
turn_store: turn_context.extension_data.as_ref(),
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
model_context_window: step_context.settings.model_info.usable_context_window(),
|
||||
})
|
||||
.await
|
||||
{
|
||||
|
||||
@@ -10810,7 +10810,7 @@ async fn record_context_updates_and_set_reference_context_item_persists_split_fi
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_initial_context_uses_retained_step_after_model_change() {
|
||||
let (session, mut turn_context, _rx_event) =
|
||||
let (mut session, mut turn_context, _rx_event) =
|
||||
make_session_and_context_with_auth_and_config_and_rx(
|
||||
CodexAuth::from_api_key("Test API Key"),
|
||||
Vec::new(),
|
||||
@@ -10821,6 +10821,17 @@ async fn build_initial_context_uses_retained_step_after_model_change() {
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let mut builder = codex_extension_api::ExtensionRegistryBuilder::new();
|
||||
builder.prompt_contributor(Arc::new(TurnContextExtensionTestContributor));
|
||||
Arc::get_mut(&mut session)
|
||||
.expect("unshared test session")
|
||||
.services
|
||||
.extensions = Arc::new(builder.build());
|
||||
turn_context
|
||||
.extension_data
|
||||
.insert(TurnContextExtensionTestState {
|
||||
expected_model_context_window: Some(64_000),
|
||||
});
|
||||
update_turn_settings_for_test(Arc::get_mut(&mut turn_context).unwrap(), |settings| {
|
||||
let model_info = Arc::make_mut(&mut settings.model_info);
|
||||
model_info.slug = "model-a".to_string();
|
||||
@@ -10859,6 +10870,7 @@ async fn build_initial_context_uses_retained_step_after_model_change() {
|
||||
let mut model_b = step_a.settings.model_info.as_ref().clone();
|
||||
model_b.slug = "model-b".to_string();
|
||||
model_b.context_window = Some(128_000);
|
||||
model_b.effective_context_window_percent = 50;
|
||||
model_b
|
||||
.model_messages
|
||||
.as_mut()
|
||||
@@ -10879,6 +10891,7 @@ async fn build_initial_context_uses_retained_step_after_model_change() {
|
||||
let initial_b = session
|
||||
.build_initial_context_with_world_state(&step_b, &world_b)
|
||||
.await;
|
||||
let turn_contributions_b = session.build_turn_context_contribution_items(&step_b).await;
|
||||
let (restored_a, restored_world) =
|
||||
crate::compact::build_compaction_initial_context(&session, &retained).await;
|
||||
|
||||
@@ -10894,6 +10907,13 @@ async fn build_initial_context_uses_retained_step_after_model_change() {
|
||||
assert!(!a_text.contains("<context_window>"));
|
||||
assert!(b_text.contains("B instructions: pragmatic"));
|
||||
assert!(!b_text.contains("A instructions:"));
|
||||
assert!(!a_text.contains("turn context extension enabled"));
|
||||
assert!(b_text.contains("turn context extension enabled"));
|
||||
assert!(
|
||||
developer_input_texts(&turn_contributions_b)
|
||||
.join("\n")
|
||||
.contains("turn context extension enabled")
|
||||
);
|
||||
assert!(
|
||||
b_text.contains("<context_window>"),
|
||||
"full-context metadata must use B's window even though the turn started without one"
|
||||
|
||||
@@ -290,13 +290,14 @@ impl Session {
|
||||
.map(|root| root.selected_root().clone())
|
||||
.collect::<Vec<_>>();
|
||||
let extension_metrics = super::extension_metrics::from_session_telemetry(
|
||||
turn_context.session_telemetry.clone(),
|
||||
step_context.session_telemetry.clone(),
|
||||
);
|
||||
for contributor in self.services.extensions.context_contributors() {
|
||||
for section in contributor
|
||||
.contribute_world_state(WorldStateContributionInput {
|
||||
thread_id: self.thread_id(),
|
||||
turn_id: turn_context.sub_id.as_str(),
|
||||
model_info: &step_context.settings.model_info,
|
||||
environments: &environments,
|
||||
ready_selected_capability_roots: &ready_selected_capability_roots,
|
||||
executor_capability_discovery: step_context
|
||||
|
||||
Reference in new issue
Block a user