claude_code_switcher/templates/
mod.rs1use crate::{settings::ClaudeSettings, snapshots::SnapshotScope};
7use anyhow::{Result, anyhow};
8
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12pub trait Template {
14 fn template_type(&self) -> TemplateType;
16
17 fn env_var_name(&self) -> &'static str;
19
20 fn create_settings(&self, api_key: &str, scope: &SnapshotScope) -> ClaudeSettings;
22
23 fn display_name(&self) -> &'static str;
25
26 fn description(&self) -> &'static str;
28
29 fn api_key_url(&self) -> Option<&'static str> {
31 None
32 }
33
34 fn requires_additional_config(&self) -> bool {
36 false
37 }
38
39 fn get_additional_config(&self) -> Result<HashMap<String, String>> {
41 Ok(HashMap::new())
42 }
43
44 fn has_variants(&self) -> bool {
46 false
47 }
48
49 fn get_variants() -> Result<Vec<Self>>
51 where
52 Self: Sized,
53 {
54 Ok(Vec::new())
55 }
56
57 fn create_interactively() -> Result<Self>
59 where
60 Self: Sized,
61 {
62 Err(anyhow!(
63 "This template does not support interactive creation"
64 ))
65 }
66}
67
68#[derive(Debug, Clone, Serialize, PartialEq)]
70pub enum TemplateType {
71 DeepSeek,
72 Zai,
73 KatCoder,
74 Kimi, Longcat,
76 MiniMax,
77 SeedCode,
78}
79
80impl<'de> Deserialize<'de> for TemplateType {
81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82 where
83 D: serde::Deserializer<'de>,
84 {
85 let s = String::deserialize(deserializer)?;
86
87 match s.as_str() {
89 "KatCoderPro" | "KatCoderAir" => Ok(TemplateType::KatCoder),
90 "DeepSeek" => Ok(TemplateType::DeepSeek),
91 "Zai" => Ok(TemplateType::Zai),
92 "K2" | "K2Thinking" => Ok(TemplateType::Kimi), "KatCoder" => Ok(TemplateType::KatCoder),
94 "Kimi" => Ok(TemplateType::Kimi),
95 "Longcat" => Ok(TemplateType::Longcat),
96 "MiniMax" => Ok(TemplateType::MiniMax),
97 "SeedCode" => Ok(TemplateType::SeedCode),
98 _ => Err(serde::de::Error::custom(format!(
99 "unknown template type: {}",
100 s
101 ))),
102 }
103 }
104}
105
106impl std::str::FromStr for TemplateType {
107 type Err = anyhow::Error;
108
109 fn from_str(s: &str) -> Result<Self> {
110 match s.to_lowercase().as_str() {
111 "deepseek" | "ds" => Ok(TemplateType::DeepSeek),
112 "glm" | "zhipu" | "zai" | "zai-china" | "zai-ch" | "zai-international" | "zai-int" => {
113 Ok(TemplateType::Zai)
114 }
115 "k2" | "moonshot" | "k2-thinking" | "k2thinking" | "kimi" | "kimi-for-coding" => {
117 Ok(TemplateType::Kimi)
118 }
119 "kat-coder" | "katcoder" | "kat" => Ok(TemplateType::KatCoder), "kat-coder-pro" | "katcoder-pro" | "katpro" => Ok(TemplateType::KatCoder), "kat-coder-air" | "katcoder-air" | "katair" => Ok(TemplateType::KatCoder), "longcat" => Ok(TemplateType::Longcat),
123 "minimax" | "minimax-anthropic" => Ok(TemplateType::MiniMax),
124 "seed-code" | "seedcode" | "seed_code" => Ok(TemplateType::SeedCode),
125 _ => Err(anyhow!(
126 "Unknown template: {}. Available templates: deepseek, glm, k2, k2-thinking, kat-coder, kimi, longcat, minimax, seed-code",
127 s
128 )),
129 }
130 }
131}
132
133impl std::fmt::Display for TemplateType {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 match self {
136 TemplateType::DeepSeek => write!(f, "deepseek"),
137 TemplateType::Zai => write!(f, "zai"),
138 TemplateType::KatCoder => write!(f, "kat-coder"),
139 TemplateType::Kimi => write!(f, "kimi"), TemplateType::Longcat => write!(f, "longcat"),
141 TemplateType::MiniMax => write!(f, "minimax"),
142 TemplateType::SeedCode => write!(f, "seed-code"),
143 }
144 }
145}
146
147pub fn get_template_type(template_str: &str) -> Result<TemplateType> {
149 template_str.parse()
150}
151
152pub fn get_all_templates() -> Vec<TemplateType> {
154 vec![
155 TemplateType::DeepSeek,
156 TemplateType::Zai,
157 TemplateType::KatCoder,
158 TemplateType::Kimi, TemplateType::Longcat,
160 TemplateType::MiniMax,
161 TemplateType::SeedCode,
162 ]
163}
164
165pub fn get_env_var_name(template_type: &TemplateType) -> &'static str {
169 match template_type {
170 TemplateType::DeepSeek => "DEEPSEEK_API_KEY",
171 TemplateType::Zai => "Z_AI_API_KEY",
172 TemplateType::KatCoder => "KAT_CODER_API_KEY",
173 TemplateType::Kimi => "MOONSHOT_API_KEY", TemplateType::Longcat => "LONGCAT_API_KEY",
175 TemplateType::MiniMax => "MINIMAX_API_KEY",
176 TemplateType::SeedCode => "ARK_API_KEY",
177 }
178}
179
180pub fn get_template_instance_with_input(
182 template_type: &TemplateType,
183 input: &str,
184) -> Box<dyn Template> {
185 match template_type {
186 TemplateType::DeepSeek => Box::new(deepseek::DeepSeekTemplate),
187 TemplateType::Zai => {
188 match input.to_lowercase().as_str() {
190 "zai-china" | "zai-ch" => Box::new(zai::ZaiTemplate::china()),
191 "zai-international" | "zai-int" => Box::new(zai::ZaiTemplate::international()),
192 _ => Box::new(zai::ZaiTemplate::china()), }
194 }
195 TemplateType::KatCoder => {
196 match input.to_lowercase().as_str() {
198 "kat-coder-pro" | "katcoder-pro" | "katpro" => {
199 Box::new(kat_coder::KatCoderTemplate::pro())
200 }
201 "kat-coder-air" | "katcoder-air" | "katair" => {
202 Box::new(kat_coder::KatCoderTemplate::air())
203 }
204 _ => Box::new(kat_coder::KatCoderTemplate::pro()), }
206 }
207 TemplateType::Kimi => {
208 match input.to_lowercase().as_str() {
210 "k2" | "moonshot" => Box::new(kimi::KimiTemplate::k2()),
211 "k2-thinking" | "k2thinking" => Box::new(kimi::KimiTemplate::k2_thinking()),
212 "kimi" | "kimi-for-coding" => Box::new(kimi::KimiTemplate::kimi_for_coding()),
213 _ => Box::new(kimi::KimiTemplate::k2()), }
215 }
216 TemplateType::Longcat => Box::new(longcat::LongcatTemplate),
217 TemplateType::MiniMax => Box::new(minimax::MiniMaxTemplate),
218 TemplateType::SeedCode => Box::new(seed_code::SeedCodeTemplate),
219 }
220}
221
222pub fn get_template_instance(template_type: &TemplateType) -> Box<dyn Template> {
224 get_template_instance_with_input(template_type, "")
225}
226
227pub fn get_template(template_type: &TemplateType) -> fn(&str, &SnapshotScope) -> ClaudeSettings {
229 match template_type {
230 TemplateType::DeepSeek => create_deepseek_template,
231 TemplateType::Zai => create_zai_template,
232 TemplateType::KatCoder => create_kat_coder_template,
233 TemplateType::Kimi => create_k2_template, TemplateType::Longcat => create_longcat_template,
235 TemplateType::MiniMax => create_minimax_template,
236 TemplateType::SeedCode => create_seed_code_template,
237 }
238}
239
240pub mod deepseek;
242pub mod kat_coder;
243pub mod kimi; pub mod longcat;
245pub mod minimax;
246pub mod seed_code;
247pub mod zai;
248
249pub use deepseek::*;
251pub use kat_coder::*;
252pub use kimi::*; pub use longcat::*;
254pub use minimax::*;
255pub use seed_code::*;
256pub use zai::*;