Skip to main content

vtcode_core/prompts/
sections.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub(crate) enum SectionBoundaryMode {
3    BracketOnly,
4    BracketOrMarkdown,
5}
6
7pub(crate) fn find_prompt_section_bounds(
8    prompt: &str,
9    section_header: &str,
10    boundary_mode: SectionBoundaryMode,
11) -> Option<(usize, usize)> {
12    fn is_section_header_line(line: &str, boundary_mode: SectionBoundaryMode) -> bool {
13        let trimmed = line.trim();
14        (trimmed.starts_with('[') && trimmed.ends_with(']'))
15            || matches!(boundary_mode, SectionBoundaryMode::BracketOrMarkdown)
16                && trimmed.starts_with("## ")
17    }
18
19    let mut offset = 0usize;
20    let mut section_start = None;
21
22    for line in prompt.split_inclusive('\n') {
23        let trimmed = line.trim();
24        if section_start.is_none() && trimmed == section_header {
25            section_start = Some(offset);
26            offset += line.len();
27            continue;
28        }
29
30        if let Some(start) = section_start
31            && is_section_header_line(line, boundary_mode)
32        {
33            return Some((start, offset));
34        }
35
36        offset += line.len();
37    }
38
39    section_start.map(|start| (start, prompt.len()))
40}
41
42#[cfg(test)]
43mod tests {
44    use super::{SectionBoundaryMode, find_prompt_section_bounds};
45
46    #[test]
47    fn markdown_boundary_mode_stops_before_next_markdown_heading() {
48        let prompt = "Base\n## Active Tools\n- a\n## Environment\n- b\n";
49        let bounds = find_prompt_section_bounds(
50            prompt,
51            "## Active Tools",
52            SectionBoundaryMode::BracketOrMarkdown,
53        )
54        .expect("section bounds");
55
56        assert_eq!(&prompt[bounds.0..bounds.1], "## Active Tools\n- a\n");
57    }
58
59    #[test]
60    fn bracket_only_mode_ignores_markdown_headings() {
61        let prompt = "Base\n[Harness Limits]\n- a\n## Environment\n- b\n";
62        let bounds = find_prompt_section_bounds(
63            prompt,
64            "[Harness Limits]",
65            SectionBoundaryMode::BracketOnly,
66        )
67        .expect("section bounds");
68
69        assert_eq!(
70            &prompt[bounds.0..bounds.1],
71            "[Harness Limits]\n- a\n## Environment\n- b\n"
72        );
73    }
74}