Fix context budgeting and compaction
- Budget now counts exact message tokens matching what assemble_api_messages sends, not raw string content. Eliminates undercounting from formatting overhead (journal headers, personality separators, working stack). - Load journal before trimming so trim accounts for journal cost. - Compact before every turn, not just after turn completion. Prevents agent_cycle surfaced memories from pushing context over budget. - Move agent_cycle orchestration from Agent::turn to Mind::start_turn — surfaced memories and reflections now precede the user message. - Move AgentCycleState from Agent to Mind — it's orchestration, not per-agent state. memory_scoring_in_flight and memory_scores stay on Agent where they belong. - Tag DMN entries as ConversationEntry::Dmn — compaction evicts them first since they're ephemeral. Compaction also prefers evicting memories over conversation when memories exceed 50% of entry tokens. - Kill /retry slash command. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
c22b8c3a6f
commit
d5e6f55da9
5 changed files with 194 additions and 170 deletions
|
|
@ -104,10 +104,6 @@ pub struct AgentCycleState {
|
|||
log_file: Option<File>,
|
||||
pub agents: Vec<AgentInfo>,
|
||||
pub last_output: AgentCycleOutput,
|
||||
/// Whether incremental memory scoring is currently running.
|
||||
pub memory_scoring_in_flight: bool,
|
||||
/// Latest per-memory scores from incremental scoring.
|
||||
pub memory_scores: Vec<(String, f64)>,
|
||||
}
|
||||
|
||||
const AGENT_CYCLE_NAMES: &[&str] = &["surface-observe", "journal", "reflect"];
|
||||
|
|
@ -134,8 +130,6 @@ impl AgentCycleState {
|
|||
reflection: None,
|
||||
sleep_secs: None,
|
||||
},
|
||||
memory_scoring_in_flight: false,
|
||||
memory_scores: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,17 +174,17 @@ impl AgentCycleState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn snapshots(&self) -> Vec<AgentSnapshot> {
|
||||
pub fn snapshots(&self, scoring_in_flight: bool, scored_count: usize) -> Vec<AgentSnapshot> {
|
||||
let mut snaps: Vec<AgentSnapshot> = self.agents.iter().map(|a| a.snapshot()).collect();
|
||||
snaps.push(AgentSnapshot {
|
||||
name: "memory-scoring".to_string(),
|
||||
pid: None,
|
||||
phase: if self.memory_scoring_in_flight {
|
||||
phase: if scoring_in_flight {
|
||||
Some("scoring...".into())
|
||||
} else if self.memory_scores.is_empty() {
|
||||
} else if scored_count == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{} scored", self.memory_scores.len()))
|
||||
Some(format!("{} scored", scored_count))
|
||||
},
|
||||
log_path: None,
|
||||
});
|
||||
|
|
@ -210,7 +204,7 @@ impl AgentCycleState {
|
|||
|
||||
/// Save current state for the Claude Code hook path.
|
||||
pub fn save(&self, session_id: &str) {
|
||||
let state = SavedAgentState { agents: self.snapshots() };
|
||||
let state = SavedAgentState { agents: self.snapshots(false, 0) };
|
||||
state.save(session_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue