Something went wrong. Try again.
A 5e storytelling engine with an LLM DM
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160//! Tests for entity note injection: the notes of the entities the//! previous turn named, appended to the next turn's system prompt.
use super::tests::{dm_for, dm_with_campaign, fake_server, sent_messages, sse_response};use crate::bus::Speaker;
use tempfile::TempDir;
/// The preamble's opening words, distinctive enough to prove the whole/// entity notes section is present or absent.const PREAMBLE_MARKER: &str = "the session's notes for the entities";
/// The system prompt of the next request the fake server captured.fn next_system_prompt( requests: &std::sync::mpsc::Receiver<super::tests::CapturedRequest>,) -> String { sent_messages(&requests.recv().unwrap())[0]["content"] .as_str() .unwrap() .to_string()}
#[test]fn a_second_turns_prompt_carries_the_note_of_an_entity_the_first_turn_named() { let world = TempDir::new().unwrap(); let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"You meet [[Vera Blackwater]] at the bar.\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_with_campaign(url, &world);
dm.turn(Speaker::Player, "I enter the tavern.").unwrap(); dm.turn(Speaker::Player, "I greet her.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(prompt.contains("### Vera Blackwater")); assert!(prompt.contains("First seen")); assert!(prompt.contains(PREAMBLE_MARKER));}
#[test]fn two_named_entities_notes_both_reach_the_next_prompt() { let world = TempDir::new().unwrap(); let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"[[Vera Blackwater]] nods to [[people/Joseph Black]].\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_with_campaign(url, &world);
dm.turn(Speaker::Player, "I enter the tavern.").unwrap(); dm.turn(Speaker::Player, "I watch them.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(prompt.contains("### Vera Blackwater")); assert!(prompt.contains("### people/Joseph Black"));}
#[test]fn a_note_edited_on_disk_between_turns_reaches_the_next_prompt() { let world = TempDir::new().unwrap(); let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"You meet [[Vera Blackwater]] at the bar.\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_with_campaign(url, &world);
dm.turn(Speaker::Player, "I enter the tavern.").unwrap(); let stub = world.path().join("entities/Vera Blackwater.md"); std::fs::write( &stub, "---\nkind: person\naliases: []\n---\n\nVera runs the tavern now.\n", ) .unwrap(); dm.turn(Speaker::Player, "I greet her.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(prompt.contains("Vera runs the tavern now.")); assert!(!prompt.contains("First seen"));}
#[test]fn an_entity_whose_note_file_is_gone_injects_nothing() { let world = TempDir::new().unwrap(); let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"You meet [[Vera Blackwater]] at the bar.\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_with_campaign(url, &world);
dm.turn(Speaker::Player, "I enter the tavern.").unwrap(); std::fs::remove_file(world.path().join("entities/Vera Blackwater.md")).unwrap(); dm.turn(Speaker::Player, "I greet her.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(!prompt.contains("### Vera Blackwater")); assert!(!prompt.contains(PREAMBLE_MARKER));}
#[test]fn a_dm_with_no_campaign_injects_nothing_and_still_turns() { let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"You meet [[Vera Blackwater]] at the bar.\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_for(url);
dm.turn(Speaker::Player, "I enter the tavern.").unwrap(); dm.turn(Speaker::Player, "I greet her.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(!prompt.contains("### Vera Blackwater")); assert!(!prompt.contains(PREAMBLE_MARKER));}
#[test]fn a_turn_that_names_nothing_injects_no_preamble() { let world = TempDir::new().unwrap(); let first_reply = "data: {\"choices\":[{\"delta\":{\"content\":\"You walk down the road.\"},\"finish_reason\":null}]}\n\n\ data: [DONE]\n\n"; let (url, requests, server) = fake_server(vec![ sse_response(first_reply), sse_response("data: [DONE]\n\n"), ]); let mut dm = dm_with_campaign(url, &world);
dm.turn(Speaker::Player, "I walk.").unwrap(); dm.turn(Speaker::Player, "I keep walking.").unwrap();
server.join().unwrap(); requests.recv().unwrap(); let prompt = next_system_prompt(&requests);
assert!(!prompt.contains(PREAMBLE_MARKER));}