mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] add configurable token budget compaction reminder (#29255)
## Why
The token-budget feature reports coarse remaining-context milestones,
but it does not give the model a configurable wrap-up prompt before
automatic compaction. A strict threshold-crossing check can also miss
resumed or reconfigured windows that are already inside the threshold.
## What changed
- Add structured `[features.token_budget]` configuration for an absolute
`reminder_threshold_tokens` and bounded `reminder_message_template`;
`{n_remaining}` is expanded when the reminder is delivered.
- Compute remaining tokens against the next effective auto-compaction
boundary, including scoped `body_after_prefix` accounting and the full
context-window limit.
- Make reminder delivery level-triggered before and after sampling, with
one-shot state owned by `AutoCompactWindow` and re-armed on compaction,
`new_context`, restore, or history replacement.
- Leave the existing initial full-window token-budget context, 25/50/75%
notices, and token-budget tools unchanged.
- Persist the resolved feature configuration in the session config lock
and regenerate the config schema.
## Validation
- `just test -p codex-core token_budget`
- `just test -p codex-core
token_budget_reminder_emits_after_crossing_compaction_threshold`
- `just test -p codex-core auto_compact_window`
- `just test -p codex-core
lock_contains_prompts_and_materializes_features`
- `just test -p codex-features`
- `just test -p codex-config`
This commit is contained in:
committed by
GitHub
Unverified
parent
b6d6be2a84
commit
6df037d47f
@@ -30,6 +30,7 @@ pub(super) struct AutoCompactWindow {
|
||||
/// not the growth itself; server-observed usage replaces estimated
|
||||
/// resume/recompute baselines when available.
|
||||
prefill_input_tokens: Option<AutoCompactWindowPrefill>,
|
||||
token_budget_reminder_delivered: bool,
|
||||
}
|
||||
|
||||
impl AutoCompactWindow {
|
||||
@@ -44,6 +45,7 @@ impl AutoCompactWindow {
|
||||
},
|
||||
new_context_window_requested: false,
|
||||
prefill_input_tokens: None,
|
||||
token_budget_reminder_delivered: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +71,14 @@ impl AutoCompactWindow {
|
||||
self.ids.previous_window_id = Some(self.ids.window_id);
|
||||
self.ids.window_id = Uuid::now_v7();
|
||||
self.new_context_window_requested = false;
|
||||
self.token_budget_reminder_delivered = false;
|
||||
(self.window_number, self.ids)
|
||||
}
|
||||
|
||||
pub(super) fn claim_token_budget_reminder(&mut self) -> bool {
|
||||
!std::mem::replace(&mut self.token_budget_reminder_delivered, true)
|
||||
}
|
||||
|
||||
pub(super) fn request_new_context_window(&mut self) {
|
||||
self.new_context_window_requested = true;
|
||||
}
|
||||
@@ -154,6 +161,8 @@ mod tests {
|
||||
);
|
||||
assert_eq!(window.window_number(), 3);
|
||||
assert_eq!(window.ids().window_id, restored_window_id);
|
||||
assert!(window.claim_token_budget_reminder());
|
||||
assert!(!window.claim_token_budget_reminder());
|
||||
window.request_new_context_window();
|
||||
assert!(window.take_new_context_window_request());
|
||||
assert!(!window.take_new_context_window_request());
|
||||
@@ -167,6 +176,7 @@ mod tests {
|
||||
assert_eq!(ids.window_id.get_version_num(), 7);
|
||||
assert_ne!(ids.window_id, restored_window_id);
|
||||
assert!(!window.take_new_context_window_request());
|
||||
assert!(window.claim_token_budget_reminder());
|
||||
|
||||
assert_eq!(
|
||||
window.snapshot(),
|
||||
|
||||
@@ -148,6 +148,10 @@ impl SessionState {
|
||||
self.auto_compact_window.snapshot()
|
||||
}
|
||||
|
||||
pub(crate) fn claim_token_budget_reminder(&mut self) -> bool {
|
||||
self.auto_compact_window.claim_token_budget_reminder()
|
||||
}
|
||||
|
||||
pub(crate) fn auto_compact_window_number(&self) -> u64 {
|
||||
self.auto_compact_window.window_number()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user