feat: make tool result pruning opt-in

This commit is contained in:
2026-09-18 19:43:29 +09:00
parent 19ee757880
commit d7917512ac
9 changed files with 97 additions and 10 deletions
+7 -1
View File
@@ -577,6 +577,8 @@ pub struct PermissionConfigPartial {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CompactionConfigPartial {
#[serde(default)]
pub prune_enabled: Option<bool>,
#[serde(default)]
pub prune_protected_tokens: Option<u64>,
#[serde(default)]
@@ -912,6 +914,7 @@ impl PermissionConfigPartial {
impl CompactionConfigPartial {
fn merge(self, upper: Self) -> Self {
Self {
prune_enabled: upper.prune_enabled.or(self.prune_enabled),
prune_protected_tokens: upper.prune_protected_tokens.or(self.prune_protected_tokens),
prune_min_savings: upper.prune_min_savings.or(self.prune_min_savings),
threshold: upper.threshold.or(self.threshold),
@@ -1223,6 +1226,7 @@ impl TryFrom<WorkerManifestConfig> for WorkerManifest {
validate_model_paths(cm, "compaction.model.auth.file")?;
}
Ok(CompactionConfig {
prune_enabled: c.prune_enabled.unwrap_or(defaults::PRUNE_ENABLED),
prune_protected_tokens: c
.prune_protected_tokens
.unwrap_or(defaults::PRUNE_PROTECTED_TOKENS),
@@ -1831,6 +1835,7 @@ mod tests {
let lower = WorkerManifestConfig {
compaction: Some(CompactionConfigPartial {
threshold: Some(50_000),
prune_enabled: Some(false),
prune_protected_tokens: Some(5_000),
..Default::default()
}),
@@ -1861,7 +1866,8 @@ mod tests {
let merged = lower.merge(upper);
let c = merged.compaction.unwrap();
assert_eq!(c.threshold, Some(80_000));
// field from lower retained when upper has None
// fields from lower retained when upper has None
assert_eq!(c.prune_enabled, Some(false));
assert_eq!(c.prune_protected_tokens, Some(5_000));
let search = merged.web.unwrap().search.unwrap();
assert_eq!(search.timeout_secs, Some(3));
+4
View File
@@ -14,6 +14,10 @@ pub const TOOL_OUTPUT_MAX_BYTES: usize = 64 * 1024;
/// See [`crate::FileUploadLimits`].
pub const FILE_UPLOAD_MAX_BYTES: usize = 256 * 1024;
/// Whether request-time tool-result pruning is enabled when `[compaction]`
/// exists. See [`crate::CompactionConfig::prune_enabled`].
pub const PRUNE_ENABLED: bool = false;
/// Token budget at the history tail protected from pruning. See
/// [`crate::CompactionConfig::prune_protected_tokens`].
pub const PRUNE_PROTECTED_TOKENS: u64 = 8000;
+17 -1
View File
@@ -768,6 +768,11 @@ pub enum ToolPermissionAction {
/// (full history summarisation). Omitting `[compaction]` disables both.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompactionConfig {
/// Whether request-time projection removes detail from old tool results.
/// Independent from the compaction thresholds below.
#[serde(default = "default_prune_enabled")]
pub prune_enabled: bool,
/// Token budget at the history tail protected from pruning.
#[serde(default = "default_prune_protected_tokens")]
pub prune_protected_tokens: u64,
@@ -868,6 +873,9 @@ pub struct CompactionConfig {
pub model: Option<ModelManifest>,
}
fn default_prune_enabled() -> bool {
defaults::PRUNE_ENABLED
}
fn default_prune_protected_tokens() -> u64 {
defaults::PRUNE_PROTECTED_TOKENS
}
@@ -914,6 +922,7 @@ fn default_result_context_max_tokens() -> u64 {
impl Default for CompactionConfig {
fn default() -> Self {
Self {
prune_enabled: default_prune_enabled(),
prune_protected_tokens: default_prune_protected_tokens(),
prune_min_savings: default_prune_min_savings(),
threshold: None,
@@ -1460,9 +1469,11 @@ model_id = "claude-sonnet-4-20250514"
#[test]
fn parse_compaction_config() {
let toml = format!("{MINIMAL_REQUIRED}\n[compaction]\nthreshold = 80000\n");
let toml =
format!("{MINIMAL_REQUIRED}\n[compaction]\nprune_enabled = false\nthreshold = 80000\n");
let manifest = WorkerManifest::from_toml(&toml).unwrap();
let c = manifest.compaction.unwrap();
assert!(!c.prune_enabled);
assert_eq!(c.prune_protected_tokens, 8000);
assert_eq!(c.prune_min_savings, 4096);
assert_eq!(c.threshold, Some(80000));
@@ -1471,6 +1482,11 @@ model_id = "claude-sonnet-4-20250514"
assert_eq!(c.worker_max_turns, Some(20));
}
#[test]
fn compaction_defaults_to_pruning_disabled() {
assert!(!CompactionConfig::default().prune_enabled);
}
#[test]
fn reject_removed_prune_protected_turns_field() {
let toml = format!("{MINIMAL_REQUIRED}\n[compaction]\nprune_protected_turns = 3\n");
+20
View File
@@ -1245,6 +1245,26 @@ mod tests {
.unwrap()
};
for name in [
"default",
"intake",
"orchestrator",
"companion",
"coder",
"reviewer",
"memory-consolidation",
] {
let role = resolve(name);
assert_eq!(
role.manifest
.compaction
.as_ref()
.map(|compaction| compaction.prune_enabled),
Some(false),
"{name} must keep pruning disabled for the experiment"
);
}
let companion = resolve("companion");
assert_eq!(
companion.manifest.model.ref_.as_deref(),