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

+5
View File
@@ -172,6 +172,7 @@ mod requirements;
mod resolved_permission_profile;
#[cfg(test)]
mod schema;
mod token_budget_startup;
pub use auth_keyring::bootstrap_auth_config;
pub use auth_keyring::resolve_bootstrap_auth_keyring_backend_kind;
pub use codex_agent_roles::AgentRoleConfig;
@@ -197,6 +198,7 @@ pub use permissions::compile_permission_profile;
pub(crate) use permissions::is_builtin_permission_profile_name;
pub use permissions::resolve_permission_profile;
pub(crate) use resolved_permission_profile::PermissionProfileState;
pub use token_budget_startup::TokenBudgetStartupConfig;
const DEFAULT_IGNORE_LARGE_UNTRACKED_DIRS: i64 = 200;
const DEFAULT_IGNORE_LARGE_UNTRACKED_FILES: i64 = 10 * 1024 * 1024;
@@ -1053,6 +1055,8 @@ pub struct Config {
/// Context-window token budget configuration, when enabled.
pub token_budget: Option<TokenBudgetConfig>,
/// Runtime snapshot of configured token-budget preferences before startup activation.
pub token_budget_startup_config: Option<TokenBudgetStartupConfig>,
/// Shared token budget for the root thread and its sub-agents.
pub rollout_budget: Option<RolloutBudgetConfig>,
/// Current-time reminder and clock tool configuration, when enabled.
@@ -4318,6 +4322,7 @@ impl Config {
ghost_snapshot,
multi_agent_v2,
token_budget,
token_budget_startup_config: None,
rollout_budget,
current_time_reminder,
sleep_tool_mode,
@@ -0,0 +1,31 @@
//! Keeps configured token-budget preferences separate from session startup activation.
//! Fresh child sessions restore this snapshot before applying their starting model's defaults;
//! history forks retain their parent's effective activation and the original snapshot.
use super::Config;
use super::ConstraintResult;
use super::TokenBudgetConfig;
use codex_features::Feature;
/// Token-budget preferences before a session applies experimental or model-owned activation.
#[derive(Debug, Clone, PartialEq)]
pub struct TokenBudgetStartupConfig {
enabled: bool,
token_budget: Option<TokenBudgetConfig>,
}
impl Config {
/// Captures configured preferences, removing any inherited startup activation first.
pub(crate) fn prepare_token_budget_for_startup(&mut self) -> ConstraintResult<()> {
if let Some(snapshot) = self.token_budget_startup_config.as_ref() {
self.features
.set_enabled(Feature::TokenBudget, snapshot.enabled)?;
self.token_budget = snapshot.token_budget.clone();
}
self.token_budget_startup_config = Some(TokenBudgetStartupConfig {
enabled: self.features.enabled(Feature::TokenBudget),
token_budget: self.token_budget.clone(),
});
Ok(())
}
}