1use 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
42pub 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
94pub 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
123pub mod review {
128 pub const SYSTEM_PROMPT: &str = include_str!("prompts/review/system.txt");
129}
130
131pub 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
140pub mod explain {
145 pub const SYSTEM_PROMPT: &str = include_str!("prompts/explain/system.txt");
146}
147
148pub mod branch {
153 pub const SYSTEM_PROMPT: &str = include_str!("prompts/branch/system.txt");
154}
155
156pub mod ask {
161 pub const SYSTEM_PROMPT: &str = include_str!("prompts/ask/system.txt");
162}