refactor(deeplink): enhance Codex provider template generation

Align deep link import with UI preset generation logic by:
- Adding complete config.toml template matching frontend defaults
- Generating safe provider name from sanitized input
- Including model_provider, reasoning_effort, and wire_api settings
- Removing minimal template that only contained base_url
- Cleaning up deprecated test file deeplink-test.html
This commit is contained in:
YoVinchen
2025-11-19 00:33:31 +08:00
parent 956e723781
commit a7f1461a33
2 changed files with 81 additions and 25 deletions

View File

@@ -130,6 +130,8 @@
} }
.info-box ul { .info-box ul {
list-style: disc;
margin-left: 20px;
color: #856404; color: #856404;
font-size: 14px; font-size: 14px;
line-height: 1.8; line-height: 1.8;
@@ -294,9 +296,9 @@
Claude Official (官方) Claude Official (官方)
</h3> </h3>
<p class="description"> <p class="description">
导入 Claude 官方 API 配置。使用官方端点 api.anthropic.com默认模型 claude-sonnet-4-20250514 导入 Claude 官方 API 配置。使用官方端点 api.anthropic.com默认模型 claude-haiku-4.1
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=claude&name=Claude%20Official&homepage=https%3A%2F%2Fclaude.ai&endpoint=https%3A%2F%2Fapi.anthropic.com%2Fv1&apiKey=sk-ant-test-demo-key-12345&model=claude-sonnet-4-20250514&notes=%E5%AE%98%E6%96%B9%E6%B5%8B%E8%AF%95%E9%85%8D%E7%BD%AE" <a href="ccswitch://v1/import?resource=provider&app=claude&name=Claude%20Official&homepage=https%3A%2F%2Fclaude.ai&endpoint=https%3A%2F%2Fapi.anthropic.com%2Fv1&apiKey=sk-ant-test-demo-key-12345&model=claude-haiku-4.1&notes=%E5%AE%98%E6%96%B9%E6%B5%8B%E8%AF%95%E9%85%8D%E7%BD%AE"
class="deep-link"> class="deep-link">
📥 导入 Claude Official 📥 导入 Claude Official
</a> </a>
@@ -308,9 +310,9 @@
Claude 测试环境 Claude 测试环境
</h3> </h3>
<p class="description"> <p class="description">
公司内部测试环境配置示例。包含备注信息,方便区分不同环境。默认模型 claude-sonnet-4-20250514 公司内部测试环境配置示例。包含备注信息,方便区分不同环境。默认模型 claude-haiku-4.1
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=claude&name=%E5%85%AC%E5%8F%B8%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83&homepage=https%3A%2F%2Ftest.company.com&endpoint=https%3A%2F%2Fapi-test.company.com%2Fv1&apiKey=sk-ant-test-company-key&model=claude-sonnet-4-20250514&notes=%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%EF%BC%8C%E4%BB%85%E4%BE%9B%E5%BC%80%E5%8F%91%E4%BD%BF%E7%94%A8" <a href="ccswitch://v1/import?resource=provider&app=claude&name=%E5%85%AC%E5%8F%B8%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83&homepage=https%3A%2F%2Ftest.company.com&endpoint=https%3A%2F%2Fapi-test.company.com%2Fv1&apiKey=sk-ant-test-company-key&model=claude-haiku-4.1&notes=%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%EF%BC%8C%E4%BB%85%E4%BE%9B%E5%BC%80%E5%8F%91%E4%BD%BF%E7%94%A8"
class="deep-link"> class="deep-link">
📥 导入测试环境 📥 导入测试环境
</a> </a>
@@ -327,9 +329,9 @@
OpenAI Official (官方) OpenAI Official (官方)
</h3> </h3>
<p class="description"> <p class="description">
导入 OpenAI 官方 API 配置。使用官方端点 api.openai.com默认模型 gpt-4o 导入 OpenAI 官方 API 配置。使用官方端点 api.openai.com默认模型 gpt-5.1
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=codex&name=OpenAI%20Official&homepage=https%3A%2F%2Fopenai.com&endpoint=https%3A%2F%2Fapi.openai.com%2Fv1&apiKey=sk-test-demo-openai-key-67890&model=gpt-4o&notes=OpenAI%20%E5%AE%98%E6%96%B9%E6%9C%8D%E5%8A%A1" <a href="ccswitch://v1/import?resource=provider&app=codex&name=OpenAI%20Official&homepage=https%3A%2F%2Fopenai.com&endpoint=https%3A%2F%2Fapi.openai.com%2Fv1&apiKey=sk-test-demo-openai-key-67890&model=gpt-5.1&notes=OpenAI%20%E5%AE%98%E6%96%B9%E6%9C%8D%E5%8A%A1"
class="deep-link"> class="deep-link">
📥 导入 OpenAI Official 📥 导入 OpenAI Official
</a> </a>
@@ -341,9 +343,9 @@
Azure OpenAI Azure OpenAI
</h3> </h3>
<p class="description"> <p class="description">
Azure 部署的 OpenAI 服务示例。适合企业用户使用 Azure 云服务。默认模型 gpt-4o Azure 部署的 OpenAI 服务示例。适合企业用户使用 Azure 云服务。默认模型 gpt-5.1
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=codex&name=Azure%20OpenAI&homepage=https%3A%2F%2Fazure.microsoft.com%2Fopenai&endpoint=https%3A%2F%2Fyour-resource.openai.azure.com%2F&apiKey=azure-test-api-key-xyz&model=gpt-4o&notes=Azure%20%E4%BC%81%E4%B8%9A%E7%89%88%E6%9C%AC" <a href="ccswitch://v1/import?resource=provider&app=codex&name=Azure%20OpenAI&homepage=https%3A%2F%2Fazure.microsoft.com%2Fopenai&endpoint=https%3A%2F%2Fyour-resource.openai.azure.com%2F&apiKey=azure-test-api-key-xyz&model=gpt-5.1&notes=Azure%20%E4%BC%81%E4%B8%9A%E7%89%88%E6%9C%AC"
class="deep-link"> class="deep-link">
📥 导入 Azure OpenAI 📥 导入 Azure OpenAI
</a> </a>
@@ -360,9 +362,9 @@
Google Gemini Official Google Gemini Official
</h3> </h3>
<p class="description"> <p class="description">
导入 Google Gemini 官方 API 配置。默认模型 gemini-2.0-flash-exp 导入 Google Gemini 官方 API 配置。默认模型 gemini-3-pro-preview
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=gemini&name=Google%20Gemini&homepage=https%3A%2F%2Fai.google.dev&endpoint=https%3A%2F%2Fgenerativelanguage.googleapis.com%2Fv1beta&apiKey=AIzaSy-test-demo-key-abc123&model=gemini-2.0-flash-exp&notes=Google%20AI%20%E5%AE%98%E6%96%B9%E6%9C%8D%E5%8A%A1" <a href="ccswitch://v1/import?resource=provider&app=gemini&name=Google%20Gemini&homepage=https%3A%2F%2Fai.google.dev&endpoint=https%3A%2F%2Fgenerativelanguage.googleapis.com%2Fv1beta&apiKey=AIzaSy-test-demo-key-abc123&model=gemini-3-pro-preview&notes=Google%20AI%20%E5%AE%98%E6%96%B9%E6%9C%8D%E5%8A%A1"
class="deep-link"> class="deep-link">
📥 导入 Google Gemini 📥 导入 Google Gemini
</a> </a>
@@ -374,9 +376,9 @@
Gemini 测试环境 Gemini 测试环境
</h3> </h3>
<p class="description"> <p class="description">
公司内部 Gemini 测试环境配置示例。用于验证 Gemini 相关深链接导入流程请求地址为https://api-gemini-test.company.com/v1beta。默认模型 gemini-2.0-flash-exp 公司内部 Gemini 测试环境配置示例。用于验证 Gemini 相关深链接导入流程请求地址为https://api-gemini-test.company.com/v1beta。默认模型 gemini-3-pro-preview
</p> </p>
<a href="ccswitch://v1/import?resource=provider&app=gemini&name=%E5%85%AC%E5%8F%B8%20Gemini%20%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83&homepage=https%3A%2F%2Fgemini-test.company.com&endpoint=https%3A%2F%2Fapi-gemini-test.company.com%2Fv1beta&apiKey=sk-gemini-test-company-key&model=gemini-2.0-flash-exp&notes=%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%20Gemini%20%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%EF%BC%8C%E4%BB%85%E4%BE%9B%E5%BC%80%E5%8F%91%E4%BD%BF%E7%94%A8" <a href="ccswitch://v1/import?resource=provider&app=gemini&name=%E5%85%AC%E5%8F%B8%20Gemini%20%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83&homepage=https%3A%2F%2Fgemini-test.company.com&endpoint=https%3A%2F%2Fapi-gemini-test.company.com%2Fv1beta&apiKey=sk-gemini-test-company-key&model=gemini-3-pro-preview&notes=%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%20Gemini%20%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%EF%BC%8C%E4%BB%85%E4%BE%9B%E5%BC%80%E5%8F%91%E4%BD%BF%E7%94%A8"
class="deep-link"> class="deep-link">
📥 导入 Gemini 测试环境 📥 导入 Gemini 测试环境
</a> </a>
@@ -431,7 +433,7 @@
<div class="form-group"> <div class="form-group">
<label>模型(可选)</label> <label>模型(可选)</label>
<input type="text" id="model" placeholder="例如: claude-sonnet-4-20250514, gpt-4o, gemini-2.0-flash-exp"> <input type="text" id="model" placeholder="例如: claude-haiku-4.1, gpt-5.1, gemini-3-pro-preview">
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -546,3 +548,4 @@
</script> </script>
</body> </body>
</html> </html>

View File

@@ -220,21 +220,74 @@ fn build_provider_from_request(
} }
AppType::Codex => { AppType::Codex => {
// Codex configuration structure // Codex configuration structure
// For Codex, we store auth.json (JSON) and config.toml (TOML string) in settings_config // For Codex, we store auth.json (JSON) and config.toml (TOML string) in settings_config
//
// 这里尽量与前端 `getCodexCustomTemplate` 的默认模板保持一致,
// 再根据深链接参数注入 base_url / model避免出现“只有 base_url 行”的极简配置,
// 让通过 UI 新建和通过深链接导入的 Codex 自定义供应商行为一致。
// Generate TOML string for config.toml // 1. 生成一个适合作为 model_provider 名的安全标识
let mut config_toml = format!( // 规则尽量与前端 codexProviderPresets.generateThirdPartyConfig 保持一致:
r#"[api] // - 转小写
base_url = "{}" // - 非 [a-z0-9_] 统一替换为下划线
"#, // - 去掉首尾下划线
request.endpoint // - 若结果为空,则使用 "custom"
let clean_provider_name = {
let raw: String = request
.name
.chars()
.filter(|c| !c.is_control())
.collect();
let lower = raw.to_lowercase();
let mut key: String = lower
.chars()
.map(|c| match c {
'a'..='z' | '0'..='9' | '_' => c,
_ => '_',
})
.collect();
// 去掉首尾下划线
while key.starts_with('_') {
key.remove(0);
}
while key.ends_with('_') {
key.pop();
}
if key.is_empty() {
"custom".to_string()
} else {
key
}
};
// 2. 模型名称:优先使用 deeplink 中的 model否则退回到 Codex 默认模型
let model_name = request
.model
.as_deref()
.unwrap_or("gpt-5-codex")
.to_string();
// 3. 端点:与 UI 中 Base URL 处理方式保持一致,去掉结尾多余的斜杠
let endpoint = request.endpoint.trim().trim_end_matches('/').to_string();
// 4. 组装 config.toml 内容
// 使用 Rust 1.58+ 的内联格式化语法,避免 clippy::uninlined_format_args 警告
let config_toml = format!(
r#"model_provider = "{clean_provider_name}"
model = "{model_name}"
model_reasoning_effort = "high"
disable_response_storage = true
[model_providers.{clean_provider_name}]
name = "{clean_provider_name}"
base_url = "{endpoint}"
wire_api = "responses"
requires_openai_auth = true
"#
); );
// Add model if provided
if let Some(model) = &request.model {
config_toml.push_str(&format!("model = \"{model}\"\n"));
}
json!({ json!({
"auth": { "auth": {
"OPENAI_API_KEY": request.api_key, "OPENAI_API_KEY": request.api_key,