cc_switch_lib/services/provider/
models.rs1use reqwest::Client;
2use serde_json::Value;
3use std::collections::HashSet;
4use std::time::Duration;
5
6use crate::error::AppError;
7
8use super::ProviderService;
9
10impl ProviderService {
11 pub async fn fetch_provider_models(
13 base_url: &str,
14 api_key: Option<&str>,
15 ) -> Result<Vec<String>, AppError> {
16 let base_url = base_url.trim().trim_end_matches('/');
17 if base_url.is_empty() {
18 return Err(AppError::localized(
19 "fetch.invalid_url",
20 "URL 不能为空",
21 "URL cannot be empty",
22 ));
23 }
24
25 let mut candidate_urls = Vec::new();
26
27 if base_url.ends_with("/models") {
29 candidate_urls.push(base_url.to_string());
30 } else {
31 candidate_urls.push(format!("{}/models", base_url));
33 if !base_url.ends_with("/v1") && !base_url.ends_with("/v1beta") {
34 candidate_urls.push(format!("{}/v1/models", base_url));
35 }
36 }
37
38 let client = Client::builder()
39 .timeout(Duration::from_secs(5))
40 .build()
41 .map_err(|e| AppError::Message(e.to_string()))?;
42
43 let mut last_err_zh = None;
44 let mut last_err_en = None;
45
46 for url in candidate_urls {
47 let mut req = client.get(&url);
48 if let Some(key) = api_key {
49 let key = key.trim();
50 req = req
52 .header("Authorization", format!("Bearer {}", key))
53 .header("x-api-key", key);
54 }
55
56 match req.send().await {
57 Ok(resp) => {
58 if resp.status().is_success() {
59 if let Ok(json) = resp.json::<Value>().await {
60 let mut models = Vec::new();
61
62 if let Some(data) = json.get("data").and_then(|d| d.as_array()) {
64 for item in data {
65 if let Some(id) = item.get("id").and_then(|i| i.as_str()) {
66 models.push(id.to_string());
67 }
68 }
69 }
70
71 if models.is_empty() {
73 if let Some(data) = json.get("models").and_then(|d| d.as_array()) {
74 for item in data {
75 if let Some(name) =
76 item.get("name").and_then(|i| i.as_str())
77 {
78 let id = name.strip_prefix("models/").unwrap_or(name);
79 models.push(id.to_string());
80 }
81 }
82 }
83 }
84
85 if models.is_empty() {
87 if let Some(arr) = json.as_array() {
88 for item in arr {
89 if let Some(id) = item.get("id").and_then(|i| i.as_str()) {
90 models.push(id.to_string());
91 }
92 }
93 }
94 }
95
96 if !models.is_empty() {
97 let mut seen = HashSet::new();
99 models.retain(|model| seen.insert(model.clone()));
100 return Ok(models);
101 } else {
102 last_err_zh =
103 Some(format!("未能在响应中找到模型列表 (URL: {})", url));
104 last_err_en =
105 Some(format!("No model list found in response (URL: {})", url));
106 }
107 } else {
108 last_err_zh = Some(format!("无法解析 JSON 响应 (URL: {})", url));
109 last_err_en =
110 Some(format!("Failed to parse JSON response (URL: {})", url));
111 }
112 } else {
113 let err = format!("HTTP {} (URL: {})", resp.status(), url);
114 last_err_zh = Some(err.clone());
115 last_err_en = Some(err);
116 }
117 }
118 Err(e) => {
119 let err = e.to_string();
120 last_err_zh = Some(err.clone());
121 last_err_en = Some(err);
122 }
123 }
124 }
125
126 let err_zh = last_err_zh.unwrap_or_else(|| "未知错误".to_string());
127 let err_en = last_err_en.unwrap_or_else(|| "Unknown error".to_string());
128 Err(AppError::localized(
129 "fetch.failed",
130 format!("拉取失败: {}", err_zh),
131 format!("Fetch failed: {}", err_en),
132 ))
133 }
134}