use agent_client_protocol::schema::v1::{ContentBlock, ContentChunk, SessionUpdate, TextContent};
use mentra::{Message, Role};
pub fn replay(history: &[Message]) -> Vec<SessionUpdate> {
history.iter().filter_map(replayed).collect()
}
fn replayed(message: &Message) -> Option<SessionUpdate> {
let text = message.text();
if text.trim().is_empty() {
return None;
}
let chunk = ContentChunk::new(ContentBlock::Text(TextContent::new(text)));
match message.role {
Role::User => Some(SessionUpdate::UserMessageChunk(chunk)),
Role::Assistant => Some(SessionUpdate::AgentMessageChunk(chunk)),
Role::Unknown(_) => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use mentra::ContentBlock as MentraContent;
fn text_of(update: &SessionUpdate) -> String {
let chunk = match update {
SessionUpdate::UserMessageChunk(chunk) | SessionUpdate::AgentMessageChunk(chunk) => {
chunk
}
other => panic!("expected a message chunk, got {other:?}"),
};
match &chunk.content {
ContentBlock::Text(text) => text.text.clone(),
other => panic!("expected text content, got {other:?}"),
}
}
#[test]
fn a_conversation_replays_in_order_and_keeps_who_said_what() {
let updates = replay(&[
Message::user(MentraContent::text("remember 41")),
Message::assistant(MentraContent::text("noted")),
]);
assert_eq!(updates.len(), 2);
assert!(matches!(updates[0], SessionUpdate::UserMessageChunk(_)));
assert_eq!(text_of(&updates[0]), "remember 41");
assert!(matches!(updates[1], SessionUpdate::AgentMessageChunk(_)));
assert_eq!(text_of(&updates[1]), "noted");
}
#[test]
fn a_message_with_no_text_is_not_replayed() {
let updates = replay(&[
Message::assistant(MentraContent::text(" ")),
Message::unknown("tool", MentraContent::text("output")),
]);
assert!(updates.is_empty());
}
#[test]
fn an_empty_history_replays_nothing() {
assert!(replay(&[]).is_empty());
}
}