use crate::types::*;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CompactionBlock {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub keep_first: Option<TurnRange>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub keep_recent: Option<CompactedSection>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub keep_compacted: Option<CompactedSection>,
#[serde(rename = "createdAt")]
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TurnRange {
#[serde(rename = "startTurn")]
pub start_turn: u32,
#[serde(rename = "endTurn")]
pub end_turn: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CompactedSection {
pub range: TurnRange,
pub messages: Vec<AgentMessage>,
}
pub struct TurnMap {
entries: Vec<(usize, usize)>,
}
impl TurnMap {
pub fn from_messages(messages: &[AgentMessage]) -> Self {
let mut entries: Vec<(usize, usize)> = Vec::new();
let mut current_turn: Option<u32> = None;
for (i, msg) in messages.iter().enumerate() {
let turn_idx = msg.turn_id().map(|t| t.turn_index);
match (turn_idx, current_turn) {
(Some(idx), Some(cur)) if idx == cur => {
if let Some(last) = entries.last_mut() {
last.1 = i;
}
}
(Some(idx), _) => {
entries.push((i, i));
current_turn = Some(idx);
}
(None, _) => {
entries.push((i, i));
current_turn = None;
}
}
}
Self { entries }
}
pub fn turn_count(&self) -> u32 {
self.entries.len() as u32
}
pub fn messages_for_range<'a>(
&self,
range: &TurnRange,
all_msgs: &'a [AgentMessage],
) -> &'a [AgentMessage] {
if range.start_turn as usize >= self.entries.len()
|| range.end_turn as usize >= self.entries.len()
{
return &[];
}
let start = self.entries[range.start_turn as usize].0;
let end = self.entries[range.end_turn as usize].1;
&all_msgs[start..=end]
}
pub fn turn_msg_range(&self, turn_index: u32) -> Option<(usize, usize)> {
self.entries.get(turn_index as usize).copied()
}
}