feat: add multi-source downloads with automatic fallback
- support GitHub, GitCode, gh-proxy, and ghfast sources - automatically try other sources when version checks fail - persist the working fallback source and sync the UI immediately - update translations, configuration migration, and source tests
This commit is contained in:
1 parent
e8093928c0
commit
03be4acf93
16 files changed
+507
-157
No files matched your search
@@ -18,6 +18,7 @@ fn gui_field_edit_preserves_comments_and_unknown_configuration() {
|
||||
auth_dir: path_to_string(&home.join("custom-auth")),
|
||||
management_secret_key: "custom-secret".to_string(),
|
||||
usage_statistics_enabled: false,
|
||||
download_source: VersionDownloadSource::Gitcode,
|
||||
prefer_gitcode_downloads: true,
|
||||
..GuiConfigFile::default()
|
||||
};
|
||||
@@ -32,6 +33,7 @@ fn gui_field_edit_preserves_comments_and_unknown_configuration() {
|
||||
assert!(content.contains("silent-start = true"));
|
||||
assert!(content.contains("management-secret-key = \"custom-secret\""));
|
||||
assert!(content.contains("usage-statistics-enabled = false"));
|
||||
assert!(content.contains("download-source = \"gitcode\""));
|
||||
assert!(content.contains("prefer-gitcode-downloads = true"));
|
||||
assert!(!content.contains("codex-session-repair-on-launch"));
|
||||
assert!(!content.contains("claude-code-working-directory"));
|
||||
@@ -91,6 +93,7 @@ fn gui_config_defaults_are_stable() {
|
||||
assert!(content.contains("management-secret-key = \"\""));
|
||||
assert!(content.contains("plugins-enabled = false"));
|
||||
assert!(content.contains("routing-strategy = \"round-robin\""));
|
||||
assert!(content.contains("download-source = \"github\""));
|
||||
assert!(content.contains("prefer-gitcode-downloads = false"));
|
||||
assert!(content.contains("request-retry = 3"));
|
||||
assert!(content.contains("max-retry-credentials = 0"));
|
||||
|
||||
@@ -212,13 +212,42 @@ fn portable_update_download_order_respects_gitcode_preference() {
|
||||
&filename,
|
||||
)];
|
||||
|
||||
let github_first = portable_update_download_urls(&asset, false);
|
||||
assert_eq!(update_download_source_name(github_first[0]), "GitHub");
|
||||
assert_eq!(update_download_source_name(github_first[1]), "GitCode");
|
||||
let github_first = portable_update_download_urls(&asset, VersionDownloadSource::Github);
|
||||
assert_eq!(update_download_source_name(&github_first[0]), "GitHub");
|
||||
assert_eq!(update_download_source_name(&github_first[1]), "GitCode");
|
||||
|
||||
let gitcode_first = portable_update_download_urls(&asset, true);
|
||||
assert_eq!(update_download_source_name(gitcode_first[0]), "GitCode");
|
||||
assert_eq!(update_download_source_name(gitcode_first[1]), "GitHub");
|
||||
let gitcode_first = portable_update_download_urls(&asset, VersionDownloadSource::Gitcode);
|
||||
assert_eq!(update_download_source_name(&gitcode_first[0]), "GitCode");
|
||||
assert_eq!(update_download_source_name(&gitcode_first[1]), "GitHub");
|
||||
|
||||
let mirror_first = portable_update_download_urls(&asset, VersionDownloadSource::GhProxy);
|
||||
assert_eq!(
|
||||
update_download_source_name(&mirror_first[0]),
|
||||
"gh-proxy.com"
|
||||
);
|
||||
assert_eq!(update_download_source_name(&mirror_first[1]), "GitHub");
|
||||
assert_eq!(update_download_source_name(&mirror_first[2]), "GitCode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_detection_candidates_try_every_available_source_once() {
|
||||
assert_eq!(
|
||||
version_download_source_candidates(VersionDownloadSource::GhFast, true),
|
||||
[
|
||||
VersionDownloadSource::GhFast,
|
||||
VersionDownloadSource::Github,
|
||||
VersionDownloadSource::Gitcode,
|
||||
VersionDownloadSource::GhProxy,
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
version_download_source_candidates(VersionDownloadSource::Gitcode, false),
|
||||
[
|
||||
VersionDownloadSource::Github,
|
||||
VersionDownloadSource::GhProxy,
|
||||
VersionDownloadSource::GhFast,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -592,7 +621,11 @@ fn synthetic_release_uses_official_asset_names_and_urls() {
|
||||
#[test]
|
||||
fn synthetic_core_release_uses_gitcode_as_download_fallback() {
|
||||
let repository = "lzt404/CLIProxyAPI";
|
||||
let release = release_from_tag_for_repositories("7.2.80", Some(repository), false);
|
||||
let release = release_from_tag_for_repositories(
|
||||
"7.2.80",
|
||||
Some(repository),
|
||||
VersionDownloadSource::Github,
|
||||
);
|
||||
let platform = CorePlatform {
|
||||
os: "windows".to_string(),
|
||||
arch: "x86_64".to_string(),
|
||||
@@ -634,6 +667,36 @@ fn gitcode_discovered_core_release_downloads_from_gitcode_first() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn github_proxy_core_release_uses_proxy_then_official_and_gitcode() {
|
||||
let release = release_from_tag_for_repositories(
|
||||
"v7.2.80",
|
||||
Some("lzt404/CLIProxyAPI"),
|
||||
VersionDownloadSource::GhFast,
|
||||
);
|
||||
let platform = CorePlatform {
|
||||
os: "windows".to_string(),
|
||||
arch: "x86_64".to_string(),
|
||||
asset_os: "windows".to_string(),
|
||||
asset_arch: "amd64".to_string(),
|
||||
archive_kind: "zip".to_string(),
|
||||
};
|
||||
let asset = select_release_asset(&release, &platform).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
core_download_source_name(&asset.browser_download_url),
|
||||
"ghfast.top"
|
||||
);
|
||||
assert_eq!(
|
||||
core_download_source_name(&asset.fallback_download_urls[0]),
|
||||
"GitHub"
|
||||
);
|
||||
assert_eq!(
|
||||
core_download_source_name(&asset.fallback_download_urls[1]),
|
||||
"GitCode"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_asset_names_cover_the_six_supported_gui_targets() {
|
||||
let targets = [
|
||||
|
||||
@@ -1039,6 +1039,7 @@ fn startup_preserves_all_user_owned_yaml_and_only_applies_gui_managed_values() {
|
||||
plugins_enabled: true,
|
||||
routing_strategy: "fill-first".to_string(),
|
||||
proxy_url: "socks5://127.0.0.1:7890".to_string(),
|
||||
download_source: VersionDownloadSource::Github,
|
||||
prefer_gitcode_downloads: false,
|
||||
routing_session_affinity: true,
|
||||
routing_session_affinity_ttl: "1h".to_string(),
|
||||
|
||||
Reference in new issue
Block a user