Skip to main content

sr_ai/
prompts.rs

1//! Centralized prompt definitions for all AI-powered commands.
2//!
3//! Prompts and schemas are stored as template files under `prompts/` and
4//! embedded at compile time via `include_str!`. Dynamic prompts use
5//! Minijinja for rendering.
6//!
7//! Directory layout:
8//! ```text
9//! crates/sr-ai/src/prompts/
10//! ├── commit/
11//! │   ├── system.txt
12//! │   ├── user.txt.j2
13//! │   ├── patch.txt.j2
14//! │   └── schema.json
15//! ├── rebase/
16//! │   ├── system.txt.j2
17//! │   ├── user.txt.j2
18//! │   └── schema.json
19//! ├── review/
20//! │   └── system.txt
21//! ├── pr/
22//! │   ├── system.txt
23//! │   └── schema.json
24//! ├── explain/
25//! │   └── system.txt
26//! ├── branch/
27//! │   └── system.txt
28//! └── ask/
29//!     └── system.txt
30//! ```
31
32use crate::commands::commit::CommitPlan;
33
34fn render(template: &str, ctx: &minijinja::Value) -> String {
35    let env = minijinja::Environment::new();
36    env.render_str(template, ctx).unwrap_or_else(|e| {
37        eprintln!("warning: prompt template render failed: {e}");
38        template.to_string()
39    })
40}
41
42// ---------------------------------------------------------------------------
43// Commit
44// ---------------------------------------------------------------------------
45
46pub mod commit {
47    use super::*;
48
49    pub const SCHEMA: &str = include_str!("prompts/commit/schema.json");
50
51    const SYSTEM_TEMPLATE: &str = include_str!("prompts/commit/system.txt.j2");
52    const USER_TEMPLATE: &str = include_str!("prompts/commit/user.txt.j2");
53    const PATCH_TEMPLATE: &str = include_str!("prompts/commit/patch.txt.j2");
54
55    pub fn system_prompt(commit_pattern: &str, type_names: &[&str]) -> String {
56        let ctx = minijinja::context! {
57            commit_pattern => commit_pattern,
58            types_list => type_names.join(", "),
59        };
60        render(SYSTEM_TEMPLATE, &ctx)
61    }
62
63    pub fn user_prompt(staged_only: bool, git_root: &str, message: Option<&str>) -> String {
64        let ctx = minijinja::context! {
65            staged_only => staged_only,
66            git_root => git_root,
67            message => message,
68        };
69        render(USER_TEMPLATE, &ctx)
70    }
71
72    pub fn patch_prompt(
73        staged_only: bool,
74        git_root: &str,
75        message: Option<&str>,
76        existing_plan: &CommitPlan,
77        unplaced_files: &[String],
78        delta_summary: &str,
79    ) -> String {
80        let plan_json =
81            serde_json::to_string_pretty(existing_plan).unwrap_or_else(|_| "{}".to_string());
82        let ctx = minijinja::context! {
83            staged_only => staged_only,
84            git_root => git_root,
85            message => message,
86            plan_json => plan_json,
87            unplaced_files => unplaced_files.join(", "),
88            delta_summary => delta_summary,
89        };
90        render(PATCH_TEMPLATE, &ctx)
91    }
92}
93
94// ---------------------------------------------------------------------------
95// Rebase
96// ---------------------------------------------------------------------------
97
98pub mod rebase {
99    use super::*;
100
101    pub const SCHEMA: &str = include_str!("prompts/rebase/schema.json");
102
103    const SYSTEM_TEMPLATE: &str = include_str!("prompts/rebase/system.txt.j2");
104    const USER_TEMPLATE: &str = include_str!("prompts/rebase/user.txt.j2");
105
106    pub fn system_prompt(commit_pattern: &str, type_names: &[&str]) -> String {
107        let ctx = minijinja::context! {
108            commit_pattern => commit_pattern,
109            types_list => type_names.join(", "),
110        };
111        render(SYSTEM_TEMPLATE, &ctx)
112    }
113
114    pub fn user_prompt(log: &str, extra: Option<&str>) -> String {
115        let ctx = minijinja::context! {
116            log => log,
117            extra => extra,
118        };
119        render(USER_TEMPLATE, &ctx)
120    }
121}
122
123// ---------------------------------------------------------------------------
124// Review
125// ---------------------------------------------------------------------------
126
127pub mod review {
128    pub const SYSTEM_PROMPT: &str = include_str!("prompts/review/system.txt");
129}
130
131// ---------------------------------------------------------------------------
132// PR
133// ---------------------------------------------------------------------------
134
135pub mod pr {
136    pub const SYSTEM_PROMPT: &str = include_str!("prompts/pr/system.txt");
137    pub const SCHEMA: &str = include_str!("prompts/pr/schema.json");
138}
139
140// ---------------------------------------------------------------------------
141// Explain
142// ---------------------------------------------------------------------------
143
144pub mod explain {
145    pub const SYSTEM_PROMPT: &str = include_str!("prompts/explain/system.txt");
146}
147
148// ---------------------------------------------------------------------------
149// Branch
150// ---------------------------------------------------------------------------
151
152pub mod branch {
153    pub const SYSTEM_PROMPT: &str = include_str!("prompts/branch/system.txt");
154}
155
156// ---------------------------------------------------------------------------
157// Ask
158// ---------------------------------------------------------------------------
159
160pub mod ask {
161    pub const SYSTEM_PROMPT: &str = include_str!("prompts/ask/system.txt");
162}