1mod client;
2mod gemini;
3mod openai_compatible;
4mod provider;
5
6pub use client::LlmClient;
7pub use gemini::GeminiClient;
8pub use openai_compatible::OpenAiCompatibleClient;
9pub use provider::Provider;
10
11use anyhow::{Context, Result};
12
13pub fn create_client() -> Result<Box<dyn LlmClient>> {
17 let (provider, api_key) =
18 Provider::detect().context("No API key found. Set OPENAI_API_KEY, DEEPSEEK_API_KEY, or GEMINI_API_KEY")?;
19
20 Ok(create_client_for_provider(provider, api_key))
21}
22
23pub fn create_client_for_provider(provider: Provider, api_key: String) -> Box<dyn LlmClient> {
25 match provider {
26 Provider::OpenAi | Provider::DeepSeek => {
27 Box::new(OpenAiCompatibleClient::new(provider, api_key))
28 }
29 Provider::Gemini => Box::new(GeminiClient::new(api_key)),
30 }
31}
32
33pub use client::{build_prompt, parse_commit_message};
35
36#[deprecated(since = "2.0.0", note = "Use OpenAiCompatibleClient or GeminiClient instead")]
38pub type DeepSeekClient = OpenAiCompatibleClient;
39
40#[deprecated(since = "2.0.0", note = "Use OpenAiCompatibleClient or GeminiClient instead")]
41pub type DeepSeekRequest = ();
42
43#[deprecated(since = "2.0.0", note = "Use OpenAiCompatibleClient or GeminiClient instead")]
44pub type DeepSeekResponse = ();
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use serial_test::serial;
50
51 fn clear_env_keys() {
52 std::env::remove_var("OPENAI_API_KEY");
53 std::env::remove_var("DEEPSEEK_API_KEY");
54 std::env::remove_var("GEMINI_API_KEY");
55 }
56
57 #[test]
58 #[serial]
59 fn test_create_client_openai() {
60 clear_env_keys();
61 std::env::set_var("OPENAI_API_KEY", "sk-test");
62
63 let client = create_client().unwrap();
64 assert_eq!(client.provider_name(), "OpenAI");
65
66 clear_env_keys();
67 }
68
69 #[test]
70 #[serial]
71 fn test_create_client_deepseek() {
72 clear_env_keys();
73 std::env::set_var("DEEPSEEK_API_KEY", "sk-deepseek");
74
75 let client = create_client().unwrap();
76 assert_eq!(client.provider_name(), "DeepSeek");
77
78 clear_env_keys();
79 }
80
81 #[test]
82 #[serial]
83 fn test_create_client_gemini() {
84 clear_env_keys();
85 std::env::set_var("GEMINI_API_KEY", "AIza-test");
86
87 let client = create_client().unwrap();
88 assert_eq!(client.provider_name(), "Gemini");
89
90 clear_env_keys();
91 }
92
93 #[test]
94 #[serial]
95 fn test_create_client_no_key() {
96 clear_env_keys();
97
98 let result = create_client();
99 assert!(result.is_err());
100
101 clear_env_keys();
102 }
103
104 #[test]
105 fn test_create_client_for_provider() {
106 let openai = create_client_for_provider(Provider::OpenAi, "key".into());
107 assert_eq!(openai.provider_name(), "OpenAI");
108
109 let deepseek = create_client_for_provider(Provider::DeepSeek, "key".into());
110 assert_eq!(deepseek.provider_name(), "DeepSeek");
111
112 let gemini = create_client_for_provider(Provider::Gemini, "key".into());
113 assert_eq!(gemini.provider_name(), "Gemini");
114 }
115}