Allow models to enable token budgeting by default (#41803)

## What changed

- Add model metadata flags for enabling token budgeting and its history-notes extension.
- Apply those activation defaults once at thread startup when the user has not explicitly configured token budgeting, while respecting managed feature requirements.
- Continue resolving model-owned prompts for the active model so model switches can use their own token-budget guidance.

## Testing

- Update the token-budget integration test to verify that model metadata activates the feature without manual configuration.

GitOrigin-RevId: 73a32623eaeabb9243e240c43da7a5e7e93e9a19
This commit is contained in:
pmccrary-oai authored and copyberry committed 2026-08-31 08:31:23 +00:00
1 parent a9519cbcdd
commit d58d0e5841
8 files changed
+60 -12

No files matched your search

+4
View File
@@ -668,6 +668,10 @@ impl Session {
let model_info = models_manager
.get_model_info(model.as_str(), &config.to_models_manager_config())
.await;
// 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);
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)
@@ -277,6 +277,8 @@ async fn submitted_sparse_updates_preserve_captured_steps_and_ordering() {
.as_mut()
.expect("model messages")
.token_budget = Some(ModelTokenBudgetConfig {
enabled: false,
use_history_notes_extension: false,
reminder_threshold_tokens: 2_000,
reminder_message_template: "{n_remaining} tokens remain.".to_string(),
guidance_message: format!("Guidance for {}.", model.slug),
+39
View File
@@ -68,6 +68,45 @@ pub(super) fn resolve_token_budget(
Some(token_budget)
}
/// Applies model activation defaults before thread extensions are initialized.
pub(super) fn apply_model_defaults(config: &mut Config, model_info: &ModelInfo) {
let Some(model_defaults) = model_info
.model_messages
.as_ref()
.and_then(|messages| messages.token_budget.as_ref())
else {
return;
};
if !model_defaults.enabled {
return;
}
let has_explicit_config = config.token_budget.is_some()
|| config
.config_layer_stack
.effective_config()
.get("features")
.and_then(|features| features.get("token_budget"))
.is_some();
if has_explicit_config {
return;
}
if config.features.enable(Feature::TokenBudget).is_err() {
return;
}
// Managed requirements can pin the feature off even when enable() succeeds.
if !config.features.enabled(Feature::TokenBudget) {
return;
}
// Keep prompts unresolved so later turns and model switches use their own defaults.
config.token_budget = Some(TokenBudgetConfig {
use_history_notes_extension: model_defaults.use_history_notes_extension,
..TokenBudgetConfig::default()
});
}
pub(super) async fn maybe_record(
sess: &Session,
turn_context: &TurnContext,