Files
codex/codex-rs/core/src/compact_token_budget.rs
T
pakrym-oai 8571b9eaa4 Install full context in compaction replacement history (#51117)
## Why

Manual, pre-turn, and post-turn compaction previously deferred rebuilding initial context until the next turn. Their saved replacement history could omit refreshed instructions and skill catalogs.

## What changed

- Install initial context during local and remote compaction, before the last real user message or summary, keeping the compaction summary last.
- Persist matching full world-state and turn-context baselines with every replacement instead of retaining only partial extension metadata.
- Build replacement context and recompute token usage for the current model even when the previous model performs compaction. Reuse that captured context for eligible current-model retries.
- Capture manual compaction context centrally and propagate preparation errors to the task runner.

## Testing

Update assertions and snapshots for context ordering, refreshed instructions, resume and fork history, current-model checkpoint baselines, and cloud skill catalog retention across compaction and resume.

GitOrigin-RevId: 8572a76c31c6884a3c580b3bbb350d49af876bd1
2026-10-05 16:10:27 +00:00

70 lines
2.7 KiB
Rust

use std::sync::Arc;
use crate::context::world_state::WorldState;
use crate::hook_runtime::PostCompactHookOutcome;
use crate::hook_runtime::PreCompactHookOutcome;
use crate::hook_runtime::run_post_compact_hooks;
use crate::hook_runtime::run_pre_compact_hooks;
use crate::session::session::Session;
use crate::session::step_context::StepContext;
use codex_analytics::CompactionTrigger;
use codex_protocol::error::CodexErr;
use codex_protocol::error::Result as CodexResult;
use codex_protocol::items::ContextCompactionItem;
use codex_protocol::items::TurnItem;
/// Runs token-budget manual compaction as a normal compaction lifecycle.
///
/// Token-budget compaction skips model/server summarization and installs a fresh context window
/// instead. It is still modeled as compaction so compact hooks and `ContextCompaction` turn items
/// observe the same lifecycle as local or remote compaction.
pub(crate) async fn run_manual_compact_task(
sess: Arc<Session>,
step_context: Arc<StepContext>,
world_state: Arc<WorldState>,
) -> CodexResult<()> {
run_compact_task_inner(&sess, &step_context, world_state, CompactionTrigger::Manual).await
}
/// Runs token-budget inline auto-compaction as a normal compaction lifecycle.
///
/// Token-budget compaction skips model/server summarization and installs a fresh context window
/// instead. It is still modeled as compaction so compact hooks and `ContextCompaction` turn items
/// observe the same lifecycle as local or remote compaction.
pub(crate) async fn run_inline_auto_compact_task(
sess: Arc<Session>,
step_context: Arc<StepContext>,
world_state: Arc<WorldState>,
) -> CodexResult<()> {
run_compact_task_inner(&sess, &step_context, world_state, CompactionTrigger::Auto).await
}
async fn run_compact_task_inner(
sess: &Arc<Session>,
step_context: &Arc<StepContext>,
world_state: Arc<WorldState>,
trigger: CompactionTrigger,
) -> CodexResult<()> {
let turn_context = &step_context.turn;
let pre_compact_outcome = run_pre_compact_hooks(sess, turn_context, trigger).await;
match pre_compact_outcome {
PreCompactHookOutcome::Continue => {}
PreCompactHookOutcome::Stopped => return Err(CodexErr::TurnAborted),
}
let compaction_item = TurnItem::ContextCompaction(ContextCompactionItem::new());
sess.emit_turn_item_started(turn_context, &compaction_item)
.await;
sess.start_new_context_window(step_context, world_state)
.await;
sess.emit_turn_item_completed(turn_context, compaction_item)
.await;
let post_compact_outcome = run_post_compact_hooks(sess, turn_context, trigger).await;
if let PostCompactHookOutcome::Stopped = post_compact_outcome {
return Err(CodexErr::TurnAborted);
}
Ok(())
}