mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 18:41:35 +08:00
- 支持 Claude Desktop 使用 Copilot/Codex OAuth 供应商
- 放开本地路由托管 OAuth 供应商校验,允许动态 Token - 新增 Claude Desktop Copilot/Codex 预设与账号选择 - 添加 OAuth proxy 回归测试
This commit is contained in:
@@ -370,17 +370,6 @@ pub fn validate_proxy_provider(provider: &Provider) -> Result<(), AppError> {
|
||||
}
|
||||
|
||||
if let Some(meta) = provider.meta.as_ref() {
|
||||
if matches!(
|
||||
meta.provider_type.as_deref(),
|
||||
Some("github_copilot") | Some("codex_oauth")
|
||||
) {
|
||||
return Err(AppError::localized(
|
||||
"claude_desktop.provider.type_unsupported",
|
||||
"Claude Desktop 本地路由模式暂不支持 Copilot 或 Codex OAuth 供应商",
|
||||
"Claude Desktop proxy mode does not support Copilot or Codex OAuth providers yet",
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(api_format) = meta.api_format.as_deref() {
|
||||
if !matches!(
|
||||
api_format,
|
||||
@@ -419,6 +408,10 @@ fn has_proxy_base_url_and_key(provider: &Provider) -> bool {
|
||||
.map(str::trim)
|
||||
.is_some_and(|value| !value.is_empty());
|
||||
|
||||
if is_managed_oauth_proxy_provider(provider) {
|
||||
return has_base_url;
|
||||
}
|
||||
|
||||
let has_key = env
|
||||
.and_then(|value| {
|
||||
[
|
||||
@@ -440,6 +433,14 @@ fn has_proxy_base_url_and_key(provider: &Provider) -> bool {
|
||||
has_base_url && has_key
|
||||
}
|
||||
|
||||
fn is_managed_oauth_proxy_provider(provider: &Provider) -> bool {
|
||||
provider
|
||||
.meta
|
||||
.as_ref()
|
||||
.and_then(|meta| meta.provider_type.as_deref())
|
||||
.is_some_and(|provider_type| matches!(provider_type, "github_copilot" | "codex_oauth"))
|
||||
}
|
||||
|
||||
pub fn validate_provider(provider: &Provider) -> Result<(), AppError> {
|
||||
if is_official_provider(provider) {
|
||||
return Ok(());
|
||||
@@ -1066,6 +1067,33 @@ mod tests {
|
||||
provider
|
||||
}
|
||||
|
||||
fn oauth_proxy_provider(id: &str, provider_type: &str, api_format: &str) -> Provider {
|
||||
let mut provider = Provider::with_id(
|
||||
id.to_string(),
|
||||
"OAuth Proxy".to_string(),
|
||||
json!({
|
||||
"env": {
|
||||
"ANTHROPIC_BASE_URL": "https://oauth-upstream.example.com"
|
||||
}
|
||||
}),
|
||||
Some("https://example.com".to_string()),
|
||||
);
|
||||
provider.meta = Some(ProviderMeta {
|
||||
claude_desktop_mode: Some(ClaudeDesktopMode::Proxy),
|
||||
api_format: Some(api_format.to_string()),
|
||||
provider_type: Some(provider_type.to_string()),
|
||||
claude_desktop_model_routes: std::collections::HashMap::from([(
|
||||
"claude-gpt-5-4".to_string(),
|
||||
ClaudeDesktopModelRoute {
|
||||
model: "gpt-5.4".to_string(),
|
||||
supports_1m: Some(false),
|
||||
},
|
||||
)]),
|
||||
..Default::default()
|
||||
});
|
||||
provider
|
||||
}
|
||||
|
||||
fn direct_provider_with_models(id: &str) -> Provider {
|
||||
let mut provider = direct_provider(id);
|
||||
provider.meta = Some(ProviderMeta {
|
||||
@@ -1163,6 +1191,29 @@ mod tests {
|
||||
assert!(!profile.to_string().contains("kimi-k2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn claude_desktop_proxy_accepts_managed_oauth_providers_without_static_key() {
|
||||
for (provider_type, api_format) in [
|
||||
("github_copilot", "openai_chat"),
|
||||
("codex_oauth", "openai_responses"),
|
||||
] {
|
||||
let provider = oauth_proxy_provider(provider_type, provider_type, api_format);
|
||||
validate_proxy_provider(&provider).expect("oauth proxy provider should validate");
|
||||
|
||||
let temp = TempDir::new().expect("tempdir");
|
||||
let paths = test_paths(temp.path());
|
||||
let db = test_db();
|
||||
apply_provider_to_paths(&db, &provider, &paths).expect("apply oauth proxy provider");
|
||||
|
||||
let profile: Value = read_json_file(&paths.profile_path).expect("read profile");
|
||||
assert_eq!(
|
||||
profile["inferenceGatewayBaseUrl"],
|
||||
json!("http://127.0.0.1:15721/claude-desktop")
|
||||
);
|
||||
assert_eq!(profile["inferenceModels"], json!(["claude-gpt-5-4"]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn claude_desktop_proxy_maps_known_route_and_rejects_unknown_route() {
|
||||
let provider = proxy_provider("proxy");
|
||||
|
||||
Reference in New Issue
Block a user