Skip to main content

vtcode_core/prompts/
render.rs

1//! Prompt environment and interaction rendering helpers.
2
3use crate::config::VTCodeConfig;
4use crate::prompts::context::PromptContext;
5use crate::prompts::temporal::generate_temporal_date_context;
6
7/// Assemble the environment addenda section for the system prompt.
8pub fn render_environment_addenda(
9    vtcode_config: Option<&VTCodeConfig>,
10    prompt_context: Option<&PromptContext>,
11) -> Option<String> {
12    let mut lines = Vec::new();
13
14    if let Some(ctx) = prompt_context
15        && !ctx.languages.is_empty()
16    {
17        lines.push(format!("- Languages: {}. Match structural-search `lang` when needed.", ctx.languages.join(", ")));
18    }
19
20    if let Some(cfg) = vtcode_config {
21        if let Some(interaction_line) = render_interaction_addendum(cfg) {
22            lines.push(interaction_line);
23        }
24
25        if cfg.mcp.enabled {
26            lines.push(
27                "- Sources: prefer MCP (including Agent Plugin servers) before external fetches when available."
28                    .to_string(),
29            );
30        }
31
32        // The system-prompt cache freezes this value at segment/session start.
33        // Do not move temporal context into a per-turn runtime appendix: doing
34        // so changes the cache prefix on every request. Date-only (no clock
35        // time) keeps the cached prefix stable all day; precise time belongs
36        // in a `<system-reminder>` history message when a task needs it.
37        if cfg.agent.include_temporal_context {
38            let date_context = generate_temporal_date_context(cfg.agent.temporal_context_use_utc);
39            let trimmed = date_context.trim();
40            let line = if let Some(rest) = trimmed.strip_prefix("Current date (UTC):") {
41                format!("- Date (UTC): {}", rest.trim())
42            } else {
43                trimmed.replacen("Current date:", "- Date:", 1).to_string()
44            };
45            lines.push(line);
46        }
47
48        if cfg.agent.include_working_directory
49            && let Some(ctx) = prompt_context
50            && let Some(cwd) = &ctx.current_directory
51        {
52            lines.push(format!("- Working directory: {}", cwd.display()));
53        }
54    }
55
56    if lines.is_empty() {
57        None
58    } else {
59        Some(format!("## Environment\n{}", lines.join("\n")))
60    }
61}
62
63/// Render the interaction addendum line based on HITL and ask_questions config.
64fn render_interaction_addendum(cfg: &VTCodeConfig) -> Option<String> {
65    match cfg.chat.ask_questions.enabled {
66        true => None,
67        false => Some(
68            "- Interaction: no `request_user_input`; make reasonable assumptions unless Planning workflow needs follow-up."
69                .to_string(),
70        ),
71    }
72}