cc_switch/config/
types.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::collections::BTreeMap;
3
4type ConfigMap = BTreeMap<String, Configuration>;
6type EnvMap = BTreeMap<String, String>;
8type JsonMap = BTreeMap<String, serde_json::Value>;
10
11#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
13pub enum StorageMode {
14 #[serde(rename = "env")]
16 #[default]
17 Env,
18 #[serde(rename = "config")]
20 Config,
21}
22
23#[derive(Serialize, Deserialize, Default, Clone)]
32pub struct Configuration {
33 pub alias_name: String,
35 pub token: String,
37 pub url: String,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub model: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub small_fast_model: Option<String>,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub max_thinking_tokens: Option<u32>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub api_timeout_ms: Option<u32>,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub claude_code_disable_nonessential_traffic: Option<u32>,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub anthropic_default_sonnet_model: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub anthropic_default_opus_model: Option<String>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub anthropic_default_haiku_model: Option<String>,
63}
64
65#[derive(Serialize, Deserialize, Default)]
70pub struct ConfigStorage {
71 pub configurations: ConfigMap,
73 pub claude_settings_dir: Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub default_storage_mode: Option<StorageMode>,
78}
79
80#[derive(Default, Clone)]
85#[allow(dead_code)]
86pub struct ClaudeSettings {
87 pub env: EnvMap,
89 pub other: JsonMap,
91}
92
93impl Serialize for ClaudeSettings {
94 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
95 where
96 S: Serializer,
97 {
98 use serde::ser::SerializeMap;
99
100 let mut map = serializer.serialize_map(Some(
101 self.other.len() + if self.env.is_empty() { 0 } else { 1 },
102 ))?;
103
104 if !self.env.is_empty() {
106 map.serialize_entry("env", &self.env)?;
107 }
108
109 for (key, value) in &self.other {
111 map.serialize_entry(key, value)?;
112 }
113
114 map.end()
115 }
116}
117
118impl<'de> Deserialize<'de> for ClaudeSettings {
119 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120 where
121 D: Deserializer<'de>,
122 {
123 #[derive(Deserialize)]
124 struct ClaudeSettingsHelper {
125 #[serde(default)]
126 env: EnvMap,
127 #[serde(flatten)]
128 other: JsonMap,
129 }
130
131 let helper = ClaudeSettingsHelper::deserialize(deserializer)?;
132 Ok(ClaudeSettings {
133 env: helper.env,
134 other: helper.other,
135 })
136 }
137}
138
139#[allow(dead_code)]
141pub struct AddCommandParams {
142 pub alias_name: String,
143 pub token: Option<String>,
144 pub url: Option<String>,
145 pub model: Option<String>,
146 pub small_fast_model: Option<String>,
147 pub max_thinking_tokens: Option<u32>,
148 pub api_timeout_ms: Option<u32>,
149 pub claude_code_disable_nonessential_traffic: Option<u32>,
150 pub anthropic_default_sonnet_model: Option<String>,
151 pub anthropic_default_opus_model: Option<String>,
152 pub anthropic_default_haiku_model: Option<String>,
153 pub force: bool,
154 pub interactive: bool,
155 pub token_arg: Option<String>,
156 pub url_arg: Option<String>,
157 pub from_file: Option<String>,
158}