Watch
1
0
Fork
You've already forked souveraine
0
souveraine/src/core/compact/config.rs
Fimeg c489aa4bb3 feat: conversation persistence, input expansion, overlay UX
- ConversationStore (JSONL + JSON metadata) wired through Backend trait,
  SessionManager, and TUI (/new, /resume, /convos commands)
- Dynamic input box: grows with content, caps at 40% terminal height,
  scrolls internally. Shift+Enter / Ctrl+J for newlines.
- Slash command autocomplete popup (filters live as you type /)
- Conversation picker overlay for /resume (modal, arrow select, Enter switch)
- Splash bloom animation, color_support module, system prompt builder
- Fixed 8 pre-existing test failures (95/95 pass)
- Archived superseded task docs, consolidated planning references
2026-05-11 16:05:43 -04:00

152 lines
5.6 KiB
Rust

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Top-level compaction configuration, mirrors [compaction] in souveraine.toml.
///
/// Per-agent-type overrides use AgentType variant names as keys:
/// "primary", "subconscious", "subagent".
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompactionConfig {
#[serde(default = "default_enabled")]
pub enabled: bool,
/// Default strategy for all agent types (overridden by per_type).
#[serde(default = "default_strategy")]
pub strategy: CompactionStrategyKind,
/// Pressure threshold for tier-1 (warn) advisory.
#[serde(default = "default_warn_pressure")]
pub warn_pressure: f32,
/// Pressure threshold for tier-2 (urgent) advisory.
#[serde(default = "default_urgent_pressure")]
pub urgent_pressure: f32,
/// Pressure threshold for tier-3 (critical) advisory.
#[serde(default = "default_critical_pressure")]
pub critical_pressure: f32,
/// Per-agent-type overrides (keys: "primary", "subconscious", "subagent").
#[serde(default)]
pub per_type: HashMap<String, AgentCompactionConfig>,
}
impl Default for CompactionConfig {
fn default() -> Self {
Self {
enabled: true,
strategy: CompactionStrategyKind::Cull,
warn_pressure: 0.80,
urgent_pressure: 0.90,
critical_pressure: 0.95,
per_type: HashMap::new(),
}
}
}
impl CompactionConfig {
/// Resolve the effective config for a given agent type.
pub fn for_agent_type(&self, agent_type: &str) -> AgentCompactionConfig {
self.per_type
.get(agent_type)
.cloned()
.unwrap_or_else(|| AgentCompactionConfig {
enabled: self.enabled,
strategy: self.strategy.clone(),
warn_pressure: self.warn_pressure,
urgent_pressure: self.urgent_pressure,
critical_pressure: self.critical_pressure,
..Default::default()
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentCompactionConfig {
#[serde(default = "default_enabled")]
pub enabled: bool,
#[serde(default = "default_strategy")]
pub strategy: CompactionStrategyKind,
/// Pressure threshold for tier-1 (warn) advisory.
#[serde(default = "default_warn_pressure")]
pub warn_pressure: f32,
/// Pressure threshold for tier-2 (urgent) advisory.
#[serde(default = "default_urgent_pressure")]
pub urgent_pressure: f32,
/// Pressure threshold for tier-3 (critical) advisory.
#[serde(default = "default_critical_pressure")]
pub critical_pressure: f32,
/// Max summary length in chars (Summary strategy). Generous default;
/// the model's output limit is the real bound, this is an upper guard.
#[serde(default = "default_max_summary")]
pub max_summary_length: usize,
/// Target KV pair count (KeyValue strategy).
#[serde(default = "default_kv_target")]
pub kv_target: usize,
/// Min messages before compaction can run.
#[serde(default = "default_min_messages")]
pub min_messages: usize,
}
impl Default for AgentCompactionConfig {
fn default() -> Self {
Self {
enabled: true,
strategy: CompactionStrategyKind::Cull,
warn_pressure: 0.80,
urgent_pressure: 0.90,
critical_pressure: 0.95,
max_summary_length: 2048,
kv_target: 8,
min_messages: 20,
}
}
}
/// Available compaction strategies. Synthesized from OpenHarness
/// (port of Claude Code's microCompact.ts / autoCompact.ts), hermes-agent,
/// claw-open, and jcode. See `docs/tasks/compaction-rebuild.md`.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CompactionStrategyKind {
/// Cheap pre-pass: replace old tool result contents with a placeholder,
/// keeping recent tool results intact. No LLM. From OpenHarness/Claude
/// Code microCompact.ts. The first response to context pressure.
Microcompact,
/// Keep system + last N messages, drop the middle. No LLM. Fast.
/// Tool-pair aware: never splits a tool call from its result.
SlidingWindow,
/// LLM-based structured summarization of oldest messages, producing a
/// 9-section boundary message (from OpenHarness/Claude Code autoCompact.ts).
Summary,
/// Drop low-value messages (greetings, acknowledgments). Role-aware:
/// never drops System or Tool messages or tool-call carriers.
Cull,
}
impl CompactionStrategyKind {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"microcompact" | "micro" | "tool_results" => Some(Self::Microcompact),
"sliding_window" | "sliding-window" | "window" => Some(Self::SlidingWindow),
"summarize" | "summary" => Some(Self::Summary),
"cull" => Some(Self::Cull),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Microcompact => "microcompact",
Self::SlidingWindow => "sliding_window",
Self::Summary => "summary",
Self::Cull => "cull",
}
}
}
// ── Default helpers ──
fn default_enabled() -> bool { true }
fn default_strategy() -> CompactionStrategyKind { CompactionStrategyKind::Cull }
fn default_warn_pressure() -> f32 { 0.80 }
fn default_urgent_pressure() -> f32 { 0.90 }
fn default_critical_pressure() -> f32 { 0.95 }
fn default_max_summary() -> usize { 32000 }
fn default_kv_target() -> usize { 16 }
fn default_min_messages() -> usize { 10 }