use locode_protocol::{ContentBlock, Message, Role};
use crate::listing::NO_SKILLS_BODY;
const OPEN: &str = "<system-reminder>";
const CLOSE: &str = "</system-reminder>";
const SENTINEL: &str = "The following skills are available for use:";
#[must_use]
pub fn listing_message(body: &str) -> Message {
Message {
role: Role::User,
content: vec![ContentBlock::Text {
text: format!("{OPEN}\n{body}\n{CLOSE}"),
}],
}
}
#[must_use]
pub fn removal_message() -> Message {
listing_message(NO_SKILLS_BODY)
}
#[must_use]
pub fn already_delivered(history: &[Message], body: &str) -> bool {
history.iter().rev().any(|m| {
m.role == Role::User
&& m.content.iter().any(|b| match b {
ContentBlock::Text { text } => text.contains(body),
_ => false,
})
})
}
#[must_use]
pub fn any_listing_delivered(history: &[Message]) -> bool {
history.iter().any(|m| {
m.role == Role::User
&& m.content.iter().any(|b| match b {
ContentBlock::Text { text } => text.contains(SENTINEL),
_ => false,
})
})
}
#[cfg(test)]
mod tests {
use super::*;
fn user(text: &str) -> Message {
Message {
role: Role::User,
content: vec![ContentBlock::Text {
text: text.to_string(),
}],
}
}
#[test]
fn wraps_the_body_in_a_user_system_reminder() {
let m = listing_message("BODY");
assert_eq!(m.role, Role::User);
let ContentBlock::Text { text } = &m.content[0] else {
panic!("text block")
};
assert_eq!(text, "<system-reminder>\nBODY\n</system-reminder>");
}
#[test]
fn delivered_iff_the_exact_body_is_present() {
let history = vec![listing_message("A\nB")];
assert!(already_delivered(&history, "A\nB"));
assert!(
!already_delivered(&history, "A\nB\nC"),
"any change re-sends"
);
assert!(!already_delivered(&[], "A"));
}
#[test]
fn a_compacted_away_listing_counts_as_undelivered() {
let body = "The following skills are available for use:\n\n- a: A";
let mut history = vec![user("earlier"), listing_message(body), user("later")];
assert!(already_delivered(&history, body));
history.retain(
|m| !matches!(&m.content[0], ContentBlock::Text { text } if text.contains(body)),
);
assert!(!already_delivered(&history, body));
}
#[test]
fn a_replayed_transcript_suppresses_re_injection() {
let body = "The following skills are available for use:\n\n- a: A";
let replayed = vec![listing_message(body), user("hello again")];
assert!(already_delivered(&replayed, body));
}
#[test]
fn removal_is_only_meaningful_after_something_was_announced() {
assert!(!any_listing_delivered(&[user("hi")]));
let history = vec![listing_message(
"The following skills are available for use:\n\n- a: A",
)];
assert!(any_listing_delivered(&history));
}
#[test]
fn an_assistant_echo_does_not_count_as_delivery() {
let assistant = Message {
role: Role::Assistant,
content: vec![ContentBlock::Text {
text: "The following skills are available for use:".to_string(),
}],
};
assert!(!any_listing_delivered(&[assistant]));
}
}