use super::types::{AgentSession, AgentTurn, TurnMetrics};
fn detect_context_compaction(turn: &AgentTurn, current_tokens: u32, prev_cumulative: u32) -> bool {
if turn.user.origin.is_context_compaction() {
return true;
}
prev_cumulative > 0 && current_tokens < prev_cumulative / 2
}
pub trait SessionAnalysisExt {
fn compute_turn_metrics(&self, max_context: Option<u32>) -> Vec<TurnMetrics>;
}
impl SessionAnalysisExt for AgentSession {
fn compute_turn_metrics(&self, max_context: Option<u32>) -> Vec<TurnMetrics> {
let mut cumulative_total = 0u32;
let mut metrics = Vec::new();
let total_turns = self.turns.len();
for (idx, turn) in self.turns.iter().enumerate() {
let turn_end_tokens = turn.cumulative_total_tokens(cumulative_total);
let context_compacted =
detect_context_compaction(turn, turn_end_tokens, cumulative_total);
let (prev_total, delta, compaction_from) = if context_compacted {
(0, turn_end_tokens, Some(cumulative_total))
} else {
let delta = turn_end_tokens.saturating_sub(cumulative_total);
(cumulative_total, delta, None)
};
let is_active = idx == total_turns - 1;
metrics.push(TurnMetrics {
turn_index: idx,
prev_total,
delta,
is_heavy: TurnMetrics::is_delta_heavy(delta, max_context),
is_active,
context_compacted,
cumulative_total: turn_end_tokens,
compaction_from,
});
cumulative_total = turn_end_tokens;
}
metrics
}
}