1use crate::config::Config;
2use crate::instruction_presets::get_instruction_preset_library;
3use crate::llm_providers::LLMProviderType;
4use anyhow::Result;
5use clap::Args;
6use std::str::FromStr;
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug)]
9pub enum DetailLevel {
10 Minimal,
11 Standard,
12 Detailed,
13}
14
15impl FromStr for DetailLevel {
16 type Err = anyhow::Error;
17
18 fn from_str(s: &str) -> Result<Self, Self::Err> {
19 match s.to_lowercase().as_str() {
20 "minimal" => Ok(Self::Minimal),
21 "standard" => Ok(Self::Standard),
22 "detailed" => Ok(Self::Detailed),
23 _ => Err(anyhow::anyhow!("Invalid detail level: {}", s)),
24 }
25 }
26}
27
28impl DetailLevel {
29 pub fn as_str(&self) -> &'static str {
30 match self {
31 Self::Minimal => "minimal",
32 Self::Standard => "standard",
33 Self::Detailed => "detailed",
34 }
35 }
36}
37
38#[derive(Args, Clone, Default, Debug)]
39pub struct CommonParams {
40 #[arg(long, help = "Override default LLM provider", value_parser = available_providers_parser)]
42 pub provider: Option<String>,
43
44 #[arg(short, long, help = "Custom instructions for this operation")]
46 pub instructions: Option<String>,
47
48 #[arg(long, help = "Select an instruction preset")]
50 pub preset: Option<String>,
51
52 #[arg(long, help = "Enable or disable Gitmoji")]
54 pub gitmoji: Option<bool>,
55
56 #[arg(
58 long,
59 help = "Set the detail level (minimal, standard, detailed)",
60 default_value = "standard"
61 )]
62 pub detail_level: String,
63}
64
65impl CommonParams {
66 pub fn apply_to_config(&self, config: &mut Config) -> Result<()> {
67 if let Some(provider) = &self.provider {
68 config.default_provider = LLMProviderType::from_str(provider)?.to_string();
69 }
70 if let Some(instructions) = &self.instructions {
71 config.set_temp_instructions(Some(instructions.clone()));
72 }
73 if let Some(preset) = &self.preset {
74 config.set_temp_preset(Some(preset.clone()));
75 }
76 if let Some(use_gitmoji) = self.gitmoji {
77 config.use_gitmoji = use_gitmoji;
78 }
79 Ok(())
80 }
81}
82
83pub fn available_providers_parser(s: &str) -> Result<String, String> {
85 let available_providers = crate::llm::get_available_provider_names();
86 if available_providers.contains(&s.to_lowercase()) && s.to_lowercase() != "test" {
87 Ok(s.to_lowercase())
88 } else {
89 Err(format!(
90 "Invalid provider. Available providers are: {}",
91 available_providers.join(", ")
92 ))
93 }
94}
95
96pub fn get_combined_instructions(config: &Config) -> String {
97 let mut prompt = String::from("\n\n");
98
99 let preset_library = get_instruction_preset_library();
100 if let Some(preset_instructions) = preset_library.get_preset(config.instruction_preset.as_str())
101 {
102 prompt.push_str(&format!(
103 "\n\nUse this style for the commit message:\n{}\n\n",
104 preset_instructions.instructions
105 ));
106 }
107
108 if !config.instructions.is_empty() {
109 prompt.push_str(&format!(
110 "\n\nAdditional instructions for the commit message:\n{}\n\n",
111 config.instructions
112 ));
113 }
114
115 prompt
116}