use std::fmt::Write as _;
use super::types::SourceExcerpt;
pub(super) fn append_source_excerpt_section(prompt: &mut String, sources: &[SourceExcerpt]) {
append_source_excerpt_section_n(prompt, sources, MAX_PROMPT_SOURCE_EXCERPTS);
}
pub(super) fn append_source_excerpt_section_n(
prompt: &mut String,
sources: &[SourceExcerpt],
take: usize,
) {
prompt.push_str("\nSource excerpts:\n");
if sources.is_empty() {
prompt.push_str("- No source excerpts.\n");
return;
}
for source in sources.iter().take(take) {
let _ = writeln!(
prompt,
"--- {} (lines {}-{})",
source.path, source.line_start, source.line_end
);
prompt.push_str(&bounded_excerpt(&source.excerpt));
prompt.push('\n');
}
}
pub(super) const CHILD_SUMMARY_EXCERPT_MAX_CHARS: usize = 2_000;
pub(crate) const SOURCE_EXCERPT_MAX_CHARS: usize = 2_400;
pub(crate) const MAX_PROMPT_SOURCE_EXCERPTS: usize = 4;
pub(crate) const CONCEPT_PAGE_SOURCE_EXCERPTS: usize = 8;
pub(crate) const NARRATIVE_PAGE_SOURCE_EXCERPTS: usize = 8;
pub(crate) const VERIFY_SOURCE_EXCERPTS: usize = 8;
pub(super) fn summary_excerpt(summary: &str) -> String {
let paragraph = summary
.trim()
.split("\n\n")
.next()
.unwrap_or_default()
.trim();
let flattened = paragraph.split_whitespace().collect::<Vec<_>>().join(" ");
let mut excerpt = flattened;
if excerpt.chars().count() > CHILD_SUMMARY_EXCERPT_MAX_CHARS {
let body_cap = CHILD_SUMMARY_EXCERPT_MAX_CHARS.saturating_sub(1);
let cap = excerpt
.char_indices()
.nth(body_cap)
.map(|(index, _)| index)
.unwrap_or(excerpt.len());
excerpt.truncate(cap);
excerpt.push('…');
}
excerpt
}
pub(super) fn bounded_excerpt(excerpt: &str) -> String {
let trimmed = excerpt.trim_end();
let cap = trimmed
.char_indices()
.nth(SOURCE_EXCERPT_MAX_CHARS)
.map(|(index, _)| index);
match cap {
Some(cap) => {
let mut bounded = trimmed[..cap].to_string();
bounded.push('…');
bounded
}
None => trimmed.to_string(),
}
}