use zeph_llm::provider::{Message, Role};
use crate::agent::Agent;
use crate::agent::tests::agent_tests::{
MockChannel, MockToolExecutor, create_test_registry, mock_provider,
};
fn make_agent() -> Agent<MockChannel> {
let mut agent = Agent::new(
mock_provider(vec![]),
MockChannel::new(vec![]),
create_test_registry(),
None,
5,
MockToolExecutor::no_tools(),
);
agent
.msg
.messages
.push(Message::from_legacy(Role::System, "system"));
agent
}
#[test]
fn select_messages_for_compression_returns_chronological_order() {
let mut agent = make_agent();
for i in 1..=10u32 {
let role = if i % 2 == 0 {
Role::User
} else {
Role::Assistant
};
agent
.msg
.messages
.push(Message::from_legacy(role, format!("message {i}")));
}
let preserve_tail = 2;
let result = agent.select_messages_for_compression(preserve_tail);
let (_, to_compress) = result.expect("enough messages to compress");
let positions: Vec<u32> = to_compress
.iter()
.map(|m| {
m.content
.strip_prefix("message ")
.and_then(|s| s.parse::<u32>().ok())
.expect("message content must be 'message N'")
})
.collect();
let mut sorted = positions.clone();
sorted.sort_unstable();
assert_eq!(
positions, sorted,
"to_compress must be in ascending chronological order (regression for #4558); \
got: {positions:?}"
);
}
#[test]
fn select_messages_for_compression_excludes_pinned() {
let mut agent = make_agent();
for i in 1..=8u32 {
let mut msg = Message::from_legacy(Role::User, format!("msg {i}"));
if i == 3 || i == 5 {
msg.metadata.focus_pinned = true;
}
agent.msg.messages.push(msg);
}
let result = agent.select_messages_for_compression(1);
let (to_remove, to_compress) = result.expect("enough messages to compress");
let msg_at = |idx: usize| agent.msg.messages[idx].content.clone();
for idx in &to_remove {
let content = msg_at(*idx);
assert!(
!agent.msg.messages[*idx].metadata.focus_pinned,
"pinned message '{content}' must not be in to_remove"
);
}
for m in &to_compress {
assert!(
!m.metadata.focus_pinned,
"pinned message '{}' must not appear in to_compress",
m.content
);
}
}