llm_kernel/provider/
mapping.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Mapping {
12 Exact,
14 Aliased(&'static str),
16 Manual,
18}
19
20impl Mapping {
21 #[must_use]
24 pub fn upstream_key(&self) -> Option<&'static str> {
25 match self {
26 Mapping::Exact => None,
27 Mapping::Aliased(k) => Some(k),
28 Mapping::Manual => None,
29 }
30 }
31}
32
33#[must_use]
44pub fn resolve(catalog_id: &str) -> Mapping {
45 match catalog_id {
46 "openai" | "zai" | "minimax" | "minimax-cn" | "deepseek" | "alibaba" | "alibaba-cn"
48 | "lmstudio" => Mapping::Exact,
49 "gemini" => Mapping::Aliased("google"),
51 "zai-cn" => Mapping::Aliased("zai"),
52 "zai-coding" | "zai-cn-coding" => Mapping::Aliased("zai-coding-plan"),
53 "kimi" => Mapping::Aliased("kimi-for-coding"),
54 "moonshot" => Mapping::Aliased("moonshotai"),
55 "alibaba-us" => Mapping::Aliased("alibaba"),
56 _ => Mapping::Manual,
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 const EXACT: &[&str] = &[
66 "openai",
67 "zai",
68 "minimax",
69 "minimax-cn",
70 "deepseek",
71 "alibaba",
72 "alibaba-cn",
73 "lmstudio",
74 ];
75 const MANUAL: &[&str] = &["native", "ve", "mimo", "ollama", "llamacpp"];
76
77 #[test]
78 fn test_exact_matches() {
79 for &id in EXACT {
80 assert_eq!(resolve(id), Mapping::Exact, "{id} should be Exact");
81 }
82 }
83
84 #[test]
85 fn test_aliased_matches() {
86 assert_eq!(resolve("gemini"), Mapping::Aliased("google"));
87 assert_eq!(resolve("zai-cn"), Mapping::Aliased("zai"));
88 assert_eq!(resolve("zai-coding"), Mapping::Aliased("zai-coding-plan"));
89 assert_eq!(
90 resolve("zai-cn-coding"),
91 Mapping::Aliased("zai-coding-plan")
92 );
93 assert_eq!(resolve("kimi"), Mapping::Aliased("kimi-for-coding"));
94 assert_eq!(resolve("moonshot"), Mapping::Aliased("moonshotai"));
95 assert_eq!(resolve("alibaba-us"), Mapping::Aliased("alibaba"));
96 }
97
98 #[test]
99 fn test_manual_matches() {
100 for &id in MANUAL {
101 assert_eq!(resolve(id), Mapping::Manual, "{id} should be Manual");
102 }
103 assert_eq!(resolve("totally-unknown"), Mapping::Manual);
104 }
105
106 #[test]
107 fn test_upstream_key_helper() {
108 assert_eq!(resolve("openai").upstream_key(), None); assert_eq!(resolve("gemini").upstream_key(), Some("google"));
110 assert_eq!(resolve("ollama").upstream_key(), None); }
112
113 #[test]
114 fn test_every_embedded_provider_is_classified() {
115 let ids = crate::provider::ProviderIndex::embedded().ids();
120 let aliased: &[&str] = &[
121 "gemini",
122 "zai-cn",
123 "zai-coding",
124 "zai-cn-coding",
125 "kimi",
126 "moonshot",
127 "alibaba-us",
128 ];
129 for id in &ids {
130 let m = resolve(id);
131 let is_exact = EXACT.contains(&id.as_str());
132 let is_aliased = aliased.contains(&id.as_str());
133 let is_manual = MANUAL.contains(&id.as_str());
134 assert!(
135 match m {
136 Mapping::Exact => is_exact,
137 Mapping::Aliased(_) => is_aliased,
138 Mapping::Manual => is_manual,
139 },
140 "provider {id} resolved to {m:?} but is not in any known bucket — \
141 add a mapping decision in resolve()"
142 );
143 }
144 }
145}