mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] add rollout token budget configuration (varlength 1/N) (#28746)
## What This PR defines the structured configuration contract for shared rollout token budgets (across ALL agent threads under 1 rollout). ```toml [features.rollout_budget] enabled = true limit_tokens = 100000 reminder_interval_tokens = 10000 sampling_token_weight = 1.0 prefill_token_weight = 0.1 ``` The reminder interval defaults to 10% of the rollout limit. Sampling and prefill weights default to `1.0`. ## Scope This PR only defines and validates configuration. It does not track usage, inject reminders, or stop a rollout. Accounting and reminders are implemented in the stacked follow-up #28494. The existing `token_budget` feature remains unchanged. `rollout_budget` has its own feature key and configuration type. ## Tests The config test verifies that the structured fields resolve into `RolloutBudgetConfig` and do not enable the existing `token_budget` feature. Local checks: - `just write-config-schema` - `just test -p codex-core load_config_resolves_rollout_budget` - `cargo check -p codex-thread-manager-sample` - `git diff --check` The full workspace test suite was not run locally.
This commit is contained in:
@@ -73,6 +73,35 @@ impl FeatureConfig for MultiAgentV2ConfigToml {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RolloutBudgetConfigToml {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub enabled: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(range(min = 1))]
|
||||
pub limit_tokens: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(range(min = 1))]
|
||||
pub reminder_interval_tokens: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(range(min = 0.0))]
|
||||
pub sampling_token_weight: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schemars(range(min = 0.0))]
|
||||
pub prefill_token_weight: Option<f64>,
|
||||
}
|
||||
|
||||
impl FeatureConfig for RolloutBudgetConfigToml {
|
||||
fn enabled(&self) -> Option<bool> {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
fn set_enabled(&mut self, enabled: bool) {
|
||||
self.enabled = Some(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(crate) struct RemovedAppsMcpPathOverrideConfigToml {
|
||||
|
||||
@@ -23,6 +23,7 @@ pub use feature_configs::NetworkProxyDomainPermissionToml;
|
||||
pub use feature_configs::NetworkProxyModeToml;
|
||||
pub use feature_configs::NetworkProxyUnixSocketPermissionToml;
|
||||
use feature_configs::RemovedAppsMcpPathOverrideConfigToml;
|
||||
pub use feature_configs::RolloutBudgetConfigToml;
|
||||
use legacy::LegacyFeatureToggles;
|
||||
pub use legacy::legacy_feature_keys;
|
||||
|
||||
@@ -203,6 +204,8 @@ pub enum Feature {
|
||||
Goals,
|
||||
/// Add current context-window metadata to model-visible context.
|
||||
TokenBudget,
|
||||
/// Track and report a shared token budget across a session's agent threads.
|
||||
RolloutBudget,
|
||||
/// Expose an input-interruptible sleep tool.
|
||||
SleepTool,
|
||||
/// Route MCP tool approval prompts through the MCP elicitation request path.
|
||||
@@ -618,6 +621,8 @@ pub struct FeaturesToml {
|
||||
pub code_mode: Option<FeatureToml<CodeModeConfigToml>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub multi_agent_v2: Option<FeatureToml<MultiAgentV2ConfigToml>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub rollout_budget: Option<FeatureToml<RolloutBudgetConfigToml>>,
|
||||
#[serde(default, rename = "apps_mcp_path_override", skip_serializing)]
|
||||
#[schemars(skip)]
|
||||
removed_apps_mcp_path_override: Option<FeatureToml<RemovedAppsMcpPathOverrideConfigToml>>,
|
||||
@@ -650,6 +655,9 @@ impl FeaturesToml {
|
||||
if let Some(enabled) = self.multi_agent_v2.as_ref().and_then(FeatureToml::enabled) {
|
||||
entries.insert(Feature::MultiAgentV2.key().to_string(), enabled);
|
||||
}
|
||||
if let Some(enabled) = self.rollout_budget.as_ref().and_then(FeatureToml::enabled) {
|
||||
entries.insert(Feature::RolloutBudget.key().to_string(), enabled);
|
||||
}
|
||||
if let Some(enabled) = self.network_proxy.as_ref().and_then(FeatureToml::enabled) {
|
||||
entries.insert(Feature::NetworkProxy.key().to_string(), enabled);
|
||||
}
|
||||
@@ -661,6 +669,7 @@ impl FeaturesToml {
|
||||
let Self {
|
||||
code_mode,
|
||||
multi_agent_v2,
|
||||
rollout_budget,
|
||||
removed_apps_mcp_path_override: _,
|
||||
network_proxy,
|
||||
entries,
|
||||
@@ -674,6 +683,8 @@ impl FeaturesToml {
|
||||
materialize_resolved_feature_enabled(code_mode, enabled);
|
||||
} else if spec.id == Feature::MultiAgentV2 {
|
||||
materialize_resolved_feature_enabled(multi_agent_v2, enabled);
|
||||
} else if spec.id == Feature::RolloutBudget {
|
||||
materialize_resolved_feature_enabled(rollout_budget, enabled);
|
||||
} else if spec.id == Feature::NetworkProxy {
|
||||
materialize_resolved_feature_enabled(network_proxy, enabled);
|
||||
} else {
|
||||
@@ -1167,6 +1178,12 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
stage: Stage::UnderDevelopment,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::RolloutBudget,
|
||||
key: "rollout_budget",
|
||||
stage: Stage::UnderDevelopment,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::SleepTool,
|
||||
key: "sleep_tool",
|
||||
|
||||
Reference in New Issue
Block a user