rig_core/providers/
xiaomimimo.rs1use crate::client;
25use crate::providers::internal::anthropic_compatible::{
26 AnthropicBaseUrl, impl_dual_dialect_provider,
27};
28use crate::providers::internal::model_listing::{ListModelEntry, impl_model_lister};
29
30pub const API_BASE_URL: &str = "https://api.xiaomimimo.com/v1";
32pub const ANTHROPIC_API_BASE_URL: &str = "https://api.xiaomimimo.com/anthropic/v1";
34
35pub const MIMO_V2_FLASH: &str = "mimo-v2-flash";
37pub const MIMO_V2_OMNI: &str = "mimo-v2-omni";
39pub const MIMO_V2_PRO: &str = "mimo-v2-pro";
41pub const MIMO_V2_5: &str = "mimo-v2.5";
43pub const MIMO_V2_5_PRO: &str = "mimo-v2.5-pro";
45
46impl_dual_dialect_provider!(
47 ext = XiaomiMimoExt,
48 builder = XiaomiMimoBuilder,
49 anthropic_ext = XiaomiMimoAnthropicExt,
50 anthropic_builder = XiaomiMimoAnthropicBuilder,
51 client_input = client::BearerAuth,
52 api_key_env = "XIAOMI_MIMO_API_KEY",
53 base_url = API_BASE_URL,
54 base_url_env = "XIAOMI_MIMO_API_BASE",
55 anthropic_provider_name = "xiaomimimo",
56 anthropic_base_url = ANTHROPIC_API_BASE_URL,
57 anthropic_base_url_env = "XIAOMI_MIMO_ANTHROPIC_API_BASE",
58);
59
60client::impl_capabilities!(
61 XiaomiMimoExt,
62 completion = super::openai::completion::GenericCompletionModel<XiaomiMimoExt, H>,
63 model_listing = XiaomiMimoModelLister<H>,
64);
65
66impl super::openai::completion::OpenAICompatibleProvider for XiaomiMimoExt {
67 const PROVIDER_NAME: &'static str = "xiaomimimo";
68
69 type StreamingUsage = super::openai::Usage;
70
71 type Response = super::openai::CompletionResponse;
72}
73
74const ANTHROPIC_BASE_URLS: AnthropicBaseUrl = AnthropicBaseUrl::new(
75 &[(API_BASE_URL, ANTHROPIC_API_BASE_URL)],
76 &["/v1", "/v1/"],
77 "/anthropic/v1",
78);
79
80impl_model_lister!(
81 XiaomiMimoModelLister,
84 Client<H>,
85 ListModelEntry,
86 "Xiaomi MiMo",
87 "/models"
88);
89
90#[cfg(test)]
91mod tests {
92 use super::{ANTHROPIC_API_BASE_URL, ANTHROPIC_BASE_URLS, API_BASE_URL};
93
94 #[test]
95 fn test_client_initialization() {
96 let _client =
97 crate::providers::xiaomimimo::Client::new("dummy-key").expect("Client::new()");
98 let _client_from_builder = crate::providers::xiaomimimo::Client::builder()
99 .api_key("dummy-key")
100 .build()
101 .expect("Client::builder()");
102 let _anthropic_client = crate::providers::xiaomimimo::AnthropicClient::new("dummy-key")
103 .expect("AnthropicClient::new()");
104 let _anthropic_client_from_builder =
105 crate::providers::xiaomimimo::AnthropicClient::builder()
106 .api_key("dummy-key")
107 .build()
108 .expect("AnthropicClient::builder()");
109 }
110
111 #[test]
112 fn normalize_openai_bases_to_anthropic_bases() {
113 assert_eq!(
114 ANTHROPIC_BASE_URLS.normalize(API_BASE_URL).as_deref(),
115 Some(ANTHROPIC_API_BASE_URL)
116 );
117 assert_eq!(
118 ANTHROPIC_BASE_URLS
119 .normalize("https://proxy.example.com/v1")
120 .as_deref(),
121 Some("https://proxy.example.com/anthropic/v1")
122 );
123 }
124
125 #[test]
126 fn normalize_preserves_existing_anthropic_base() {
127 assert_eq!(
128 ANTHROPIC_BASE_URLS
129 .normalize(ANTHROPIC_API_BASE_URL)
130 .as_deref(),
131 Some(ANTHROPIC_API_BASE_URL)
132 );
133 }
134
135 #[test]
136 fn anthropic_primary_override_wins() {
137 let override_url = ANTHROPIC_BASE_URLS.resolve(
138 Some("https://primary.example.com/anthropic/v1"),
139 Some(API_BASE_URL),
140 );
141
142 assert_eq!(
143 override_url.as_deref(),
144 Some("https://primary.example.com/anthropic/v1")
145 );
146 }
147}