Gate experimental context by model capability at session startup (#43147)

## Why

Experimental context activation previously checked the provider and account eligibility without checking model support. Child sessions also inherited token-budget activation from their parent, even when starting fresh with a different model.

## What changed

- Add `ModelInfo.supports_experimental_context`, defaulting to `false`, and enable it for the bundled `gpt-6-astra` model. Require this capability when activating experimental context.
- Snapshot configured token-budget preferences before startup activation. Restore them for fresh child sessions before applying their starting model's defaults, while history forks retain their parent's activation.
- Pass unresolved token-budget preferences to child sessions so they can use their own model's prompts.

## Testing

Extend coverage for unsupported models, model-switch guidance under explicit and experimental activation, and child configuration from both active and inactive parents. Verify that omitted capability metadata defaults to `false`.

GitOrigin-RevId: 02df9e171682267232fa923d5ea3f7af36527808
This commit is contained in:
pmccrary-oai authored and copyberry committed 2026-09-06 02:28:38 +00:00
1 parent 1c40ffe427
commit 6af345407d
21 files changed
+128 -15

No files matched your search

+16 -5
View File
@@ -687,11 +687,22 @@ impl Session {
.get_model_info(model.as_str(), &config.to_models_manager_config())
.await;
let auth = auth_manager.auth_cached();
token_budget::apply_experimental_context(Arc::make_mut(&mut config), auth.as_ref())?;
// Intentionally resolve `enabled` and `use_history_notes_extension` only at
// thread startup. Both activation flags stay fixed for this thread runtime,
// even if the selected model changes later.
token_budget::apply_model_defaults(Arc::make_mut(&mut config), &model_info);
// Forked subagents keep their parent's activation with the copied history.
// Fresh children restore configured preferences before applying startup defaults.
let inherits_token_budget = matches!(&conversation_history, InitialHistory::Forked(_))
&& config.token_budget_startup_config.is_some();
if !inherits_token_budget {
Arc::make_mut(&mut config)
.prepare_token_budget_for_startup()
.map_err(|err| CodexErr::InvalidRequest(err.to_string()))?;
// Resolve activation for this runtime, including when resuming saved history.
token_budget::apply_experimental_context(
Arc::make_mut(&mut config),
auth.as_ref(),
&model_info,
)?;
token_budget::apply_model_defaults(Arc::make_mut(&mut config), &model_info);
}
let configured_config = Arc::clone(&config);
let multi_agent_version = config.multi_agent_version_override().or_else(|| {
resolve_multi_agent_version(&conversation_history, inherited_multi_agent_version)
@@ -21,9 +21,11 @@ fn experimental_context_is_eligible(auth_mode: AuthMode, plan_type: Option<PlanT
pub(super) fn apply_experimental_context(
config: &mut Config,
auth: Option<&CodexAuth>,
starting_model: &ModelInfo,
) -> std::io::Result<()> {
let provider = &config.model_provider;
if !config.features.enabled(Feature::ContextManagement)
|| !starting_model.supports_experimental_context
|| !provider.supports_codex_backend_routes()
|| !provider.requires_openai_auth
|| provider.env_key.is_some()