Run progressive compaction alongside foreground provider work
This commit is contained in:
@@ -260,6 +260,24 @@ impl ProviderRunCoordinator {
|
||||
.or(self.max_context_tokens)
|
||||
}
|
||||
|
||||
/// Leave enough history space for a command-monitor turn before switching
|
||||
/// profiles, accounting for each profile's own fixed prompt and output budget.
|
||||
pub(crate) fn progressive_summary_context_budget(&self) -> Option<(u32, u32)> {
|
||||
[self.run.profile().as_str(), CLI_MONITOR_PROVIDER_PROFILE]
|
||||
.into_iter()
|
||||
.filter_map(|name| {
|
||||
let profile = self.profiles.get(name)?;
|
||||
let limit = profile.max_context_tokens.or(self.max_context_tokens)?;
|
||||
let mut request = profile.request.clone();
|
||||
request.prompt = None;
|
||||
request.messages.clear();
|
||||
let fixed = u32::try_from(estimate_turn_request_tokens(&request))
|
||||
.unwrap_or(u32::MAX);
|
||||
Some((limit, fixed))
|
||||
})
|
||||
.min_by_key(|(limit, fixed)| limit.saturating_sub(*fixed))
|
||||
}
|
||||
|
||||
/// Includes the current transcript, fixed request context, tools, and output reservation.
|
||||
/// Read at the model boundary so newly committed tool output is included.
|
||||
pub(crate) fn estimated_context_tokens(&self) -> Option<(u32, u32)> {
|
||||
|
||||
@@ -1608,6 +1608,118 @@ async fn compaction_boundary_keeps_the_monitor_context_limit() {
|
||||
assert_eq!(coordinator.current_context_limit(), Some(100_000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn progressive_summary_budget_anticipates_switching_to_a_smaller_monitor() {
|
||||
let runtime = Arc::new(ScriptedRuntime::new(vec![]));
|
||||
let mut coordinator = coordinator(runtime.clone());
|
||||
coordinator.set_max_context_tokens(Some(500_000));
|
||||
coordinator
|
||||
.insert_profile(
|
||||
CLI_MONITOR_PROVIDER_PROFILE,
|
||||
ProviderRunProfile::new(runtime, request()).with_max_context_tokens(Some(275_000)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(coordinator.current_context_limit(), Some(500_000));
|
||||
assert_eq!(
|
||||
coordinator
|
||||
.progressive_summary_context_budget()
|
||||
.map(|(limit, _)| limit),
|
||||
Some(275_000)
|
||||
);
|
||||
|
||||
coordinator
|
||||
.run_mut()
|
||||
.set_ready_profile(CLI_MONITOR_PROVIDER_PROFILE)
|
||||
.unwrap();
|
||||
assert_eq!(coordinator.current_context_limit(), Some(275_000));
|
||||
assert_eq!(
|
||||
coordinator
|
||||
.progressive_summary_context_budget()
|
||||
.map(|(limit, _)| limit),
|
||||
Some(275_000)
|
||||
);
|
||||
|
||||
coordinator
|
||||
.run_mut()
|
||||
.set_ready_profile(BASE_PROVIDER_PROFILE)
|
||||
.unwrap();
|
||||
assert_eq!(coordinator.current_context_limit(), Some(500_000));
|
||||
assert_eq!(
|
||||
coordinator
|
||||
.progressive_summary_context_budget()
|
||||
.map(|(limit, _)| limit),
|
||||
Some(275_000)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn progressive_summary_budget_respects_smaller_active_limits_and_profile_fallbacks() {
|
||||
for (base_limit, monitor_limit, fallback_limit, expected) in [
|
||||
(
|
||||
Some(200_000),
|
||||
Some(Some(275_000)),
|
||||
Some(500_000),
|
||||
Some(200_000),
|
||||
),
|
||||
(Some(500_000), Some(None), Some(275_000), Some(275_000)),
|
||||
(Some(500_000), None, Some(275_000), Some(500_000)),
|
||||
(None, None, None, None),
|
||||
] {
|
||||
let runtime = Arc::new(ScriptedRuntime::new(vec![]));
|
||||
let mut coordinator = ProviderRunCoordinator::from_request(
|
||||
"progressive-summary-budget",
|
||||
ProviderRunProfile::new(runtime.clone(), request()).with_max_context_tokens(base_limit),
|
||||
Vec::new(),
|
||||
ProviderRunLimits::default(),
|
||||
)
|
||||
.unwrap();
|
||||
coordinator.set_max_context_tokens(fallback_limit);
|
||||
if let Some(monitor_limit) = monitor_limit {
|
||||
coordinator
|
||||
.insert_profile(
|
||||
CLI_MONITOR_PROVIDER_PROFILE,
|
||||
ProviderRunProfile::new(runtime, request())
|
||||
.with_max_context_tokens(monitor_limit),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
coordinator.current_context_limit(),
|
||||
base_limit.or(fallback_limit)
|
||||
);
|
||||
assert_eq!(
|
||||
coordinator
|
||||
.progressive_summary_context_budget()
|
||||
.map(|(limit, _)| limit),
|
||||
expected
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn progressive_summary_budget_accounts_for_output_reservations_when_selecting_a_profile() {
|
||||
let runtime = Arc::new(ScriptedRuntime::new(vec![]));
|
||||
let mut coordinator = coordinator(runtime.clone());
|
||||
coordinator.set_max_context_tokens(Some(275_000));
|
||||
let mut monitor_request = request();
|
||||
monitor_request.max_output_tokens = Some(300_000);
|
||||
coordinator
|
||||
.insert_profile(
|
||||
CLI_MONITOR_PROVIDER_PROFILE,
|
||||
ProviderRunProfile::new(runtime, monitor_request)
|
||||
.with_max_context_tokens(Some(500_000)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (limit, persistent_tokens) = coordinator.progressive_summary_context_budget().unwrap();
|
||||
|
||||
assert_eq!(coordinator.current_context_limit(), Some(275_000));
|
||||
assert_eq!(limit, 500_000);
|
||||
assert!(persistent_tokens > 300_000);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn monitor_request_uses_its_profile_context_limit() {
|
||||
let base_runtime = Arc::new(ScriptedRuntime::new(vec![answer_turn()]));
|
||||
|
||||
Reference in New Issue
Block a user