use super::token::TokenCounter;
use super::{BlockCompactionStrategy, CompactionStrategy};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CompactionScope {
FixedCount(usize),
TokenBudget,
}
impl Default for CompactionScope {
fn default() -> Self {
Self::FixedCount(3)
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct CompactionConfig {
pub compact_at_pct: f64,
pub compact_budget_threshold_pct: f64,
pub compaction_scope: CompactionScope,
pub keep_first_turns: usize,
pub keep_recent_turns: usize,
pub max_summary_tokens: usize,
pub tool_output_max_lines: usize,
#[serde(default)]
pub focus_message: Option<String>,
#[serde(skip)]
pub in_memory_strategy: Option<Arc<dyn CompactionStrategy>>,
#[serde(skip)]
pub block_strategy: Option<Arc<dyn BlockCompactionStrategy>>,
}
impl std::fmt::Debug for CompactionConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CompactionConfig")
.field("compact_at_pct", &self.compact_at_pct)
.field(
"compact_budget_threshold_pct",
&self.compact_budget_threshold_pct,
)
.field("compaction_scope", &self.compaction_scope)
.field("keep_first_turns", &self.keep_first_turns)
.field("keep_recent_turns", &self.keep_recent_turns)
.field("max_summary_tokens", &self.max_summary_tokens)
.field("tool_output_max_lines", &self.tool_output_max_lines)
.field("focus_message", &self.focus_message)
.field(
"in_memory_strategy",
&self.in_memory_strategy.as_ref().map(|_| "..."),
)
.field(
"block_strategy",
&self.block_strategy.as_ref().map(|_| "..."),
)
.finish()
}
}
impl Default for CompactionConfig {
fn default() -> Self {
Self {
compact_at_pct: 0.90,
compact_budget_threshold_pct: 0.05,
compaction_scope: CompactionScope::default(),
keep_first_turns: 2,
keep_recent_turns: 10,
max_summary_tokens: 2_000,
tool_output_max_lines: 50,
focus_message: None,
in_memory_strategy: None,
block_strategy: None,
}
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct ContextConfig {
pub max_context_tokens: usize,
pub system_prompt_tokens: usize,
pub compaction: CompactionConfig,
#[serde(skip)]
pub token_counter: Option<Arc<dyn TokenCounter>>,
#[serde(default)]
pub keep_recent: usize,
#[serde(default)]
pub keep_first: usize,
#[serde(default)]
pub tool_output_max_lines: usize,
}
impl std::fmt::Debug for ContextConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContextConfig")
.field("max_context_tokens", &self.max_context_tokens)
.field("system_prompt_tokens", &self.system_prompt_tokens)
.field("compaction", &self.compaction)
.field("token_counter", &self.token_counter.as_ref().map(|_| "..."))
.finish()
}
}
impl ContextConfig {
pub fn counter(&self) -> &dyn TokenCounter {
self.token_counter
.as_deref()
.unwrap_or(&super::token::HeuristicTokenCounter)
}
}
impl Default for ContextConfig {
fn default() -> Self {
Self {
max_context_tokens: 100_000,
system_prompt_tokens: 4_000,
compaction: CompactionConfig::default(),
token_counter: None,
keep_recent: 10,
keep_first: 2,
tool_output_max_lines: 50,
}
}
}