From b8b48a99ba8d9e17398886a005c7c64f011ad6f3 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Wed, 22 Apr 2026 07:51:46 -0400 Subject: [PATCH] hotfix(cliproxy): fallback from deleted CLIProxyAPIPlus to original backend The upstream router-for-me/CLIProxyAPIPlus repo was deleted, breaking any install/update path that resolved backend: plus. Existing users with `backend: plus` saved in config.yaml hit 404s on every bootstrap. Changes: - Flip DEFAULT_BACKEND from 'plus' to 'original' (platform-detector.ts) - Flip default cliproxy.backend in createEmptyUnifiedConfig() to 'original' - Runtime 404 fallback: getConfiguredBackend() degrades 'plus' -> 'original' with a one-time warning, so existing installations keep working without a manual reconfig step - Update CLIProxyBackend docblock to document the fallback behavior - Update tests to match new default Retains the 'plus' type and BACKEND_CONFIG entry for forward compatibility once CCS self-maintains its own Plus fork. Closes #1062 --- src/cliproxy/binary-manager.ts | 34 +++++++++++++++++-- src/cliproxy/platform-detector.ts | 11 ++++-- src/cliproxy/types.ts | 6 ++-- src/config/unified-config-types.ts | 2 +- tests/unit/cliproxy/backend-selection.test.js | 19 ++++++----- .../cliproxy/binary-manager-install.test.ts | 2 +- 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/cliproxy/binary-manager.ts b/src/cliproxy/binary-manager.ts index 452bd162..1a4237aa 100644 --- a/src/cliproxy/binary-manager.ts +++ b/src/cliproxy/binary-manager.ts @@ -32,15 +32,43 @@ import { import type { CLIProxyBackend } from './types'; /** - * Get backend from config or default to 'plus' + * Track whether we've already warned the user about the Plus fallback this + * process lifetime. Prevents spamming the warning on every command. + */ +let plusFallbackWarned = false; + +/** + * Get backend from config, with runtime fallback to 'original' when the user + * still has `backend: plus` saved. + * + * Context (issue #1062): the upstream `router-for-me/CLIProxyAPIPlus` repo was + * deleted, so any `backend: plus` install/update path hits a 404. Rather than + * forcing users to manually edit config.yaml, we degrade to `original` at + * runtime and warn once. This keeps existing installations working without a + * reconfig step, while CCS self-maintains its own Plus fork (future work). */ function getConfiguredBackend(): CLIProxyBackend { + let configured: CLIProxyBackend; try { const config = loadOrCreateUnifiedConfig(); - return config.cliproxy?.backend || DEFAULT_BACKEND; + configured = config.cliproxy?.backend || DEFAULT_BACKEND; } catch { return DEFAULT_BACKEND; } + + if (configured === 'plus') { + if (!plusFallbackWarned) { + plusFallbackWarned = true; + warn( + 'CLIProxyAPIPlus upstream repo is currently unavailable; falling back to ' + + '`backend: original`. Run `ccs config` to update your saved config. ' + + 'Tracking: https://github.com/kaitranntt/ccs/issues/1062' + ); + } + return 'original'; + } + + return configured; } /** @@ -52,7 +80,7 @@ function getBackendBinDir(backend: CLIProxyBackend = DEFAULT_BACKEND): string { return `${baseDir}/${backend}`; } -/** Default configuration (uses backend from config.yaml or defaults to 'plus') */ +/** Default configuration (uses backend from config.yaml or defaults to `DEFAULT_BACKEND`) */ function createDefaultConfig(backend: CLIProxyBackend = DEFAULT_BACKEND): BinaryManagerConfig { const backendConfig = BACKEND_CONFIG[backend]; return { diff --git a/src/cliproxy/platform-detector.ts b/src/cliproxy/platform-detector.ts index f5493f50..6c73c533 100644 --- a/src/cliproxy/platform-detector.ts +++ b/src/cliproxy/platform-detector.ts @@ -29,8 +29,15 @@ export const BACKEND_CONFIG = { }, } as const; -/** Default backend */ -export const DEFAULT_BACKEND: CLIProxyBackend = 'plus'; +/** + * Default backend + * + * Set to 'original' because upstream `router-for-me/CLIProxyAPIPlus` was + * deleted (issue #1062). The original `router-for-me/CLIProxyAPI` repo is + * still maintained. Users with existing `backend: plus` configs are migrated + * at runtime via a 404 fallback in the installer (see binary/installer.ts). + */ +export const DEFAULT_BACKEND: CLIProxyBackend = 'original'; /** * CLIProxyAPIPlus fallback version (used when GitHub API unavailable) diff --git a/src/cliproxy/types.ts b/src/cliproxy/types.ts index ea723480..37686a50 100644 --- a/src/cliproxy/types.ts +++ b/src/cliproxy/types.ts @@ -148,8 +148,10 @@ export type CLIProxyProvider = /** * CLIProxy backend selection - * - original: CLIProxyAPI (legacy provider subset) - * - plus: CLIProxyAPIPlus (expanded provider support, default) + * - original: CLIProxyAPI (current default; upstream still maintained) + * - plus: CLIProxyAPIPlus (expanded provider support; upstream deleted as of + * issue #1062 — runtime falls back to `original`. Retained for forward + * compatibility once CCS self-maintains its own Plus build.) */ export type CLIProxyBackend = 'original' | 'plus'; diff --git a/src/config/unified-config-types.ts b/src/config/unified-config-types.ts index 6b294857..472bd168 100644 --- a/src/config/unified-config-types.ts +++ b/src/config/unified-config-types.ts @@ -1016,7 +1016,7 @@ export function createEmptyUnifiedConfig(): UnifiedConfig { accounts: {}, profiles: {}, cliproxy: { - backend: 'plus', + backend: 'original', oauth_accounts: {}, providers: [...CLIPROXY_SUPPORTED_PROVIDERS], variants: {}, diff --git a/tests/unit/cliproxy/backend-selection.test.js b/tests/unit/cliproxy/backend-selection.test.js index ff2ead96..2a36c93e 100644 --- a/tests/unit/cliproxy/backend-selection.test.js +++ b/tests/unit/cliproxy/backend-selection.test.js @@ -28,8 +28,8 @@ describe('Backend Selection', () => { }); describe('DEFAULT_BACKEND', () => { - it('defaults to plus backend for backward compatibility', () => { - assert.strictEqual(platformDetector.DEFAULT_BACKEND, 'plus'); + it('defaults to original backend (Plus upstream deleted, issue #1062)', () => { + assert.strictEqual(platformDetector.DEFAULT_BACKEND, 'original'); }); }); @@ -45,9 +45,10 @@ describe('Backend Selection', () => { assert(info.binaryName.startsWith('CLIProxyAPIPlus_6.6.51-0_')); }); - it('uses plus backend by default', () => { + it('uses original backend by default (Plus upstream deleted, issue #1062)', () => { const info = platformDetector.detectPlatform(); - assert(info.binaryName.includes('CLIProxyAPIPlus')); + assert(info.binaryName.startsWith('CLIProxyAPI_')); + assert(!info.binaryName.includes('CLIProxyAPIPlus')); }); it('uses fallback version when version not specified', () => { @@ -76,9 +77,10 @@ describe('Backend Selection', () => { assert.strictEqual(name, expected); }); - it('defaults to plus backend', () => { + it('defaults to original backend (Plus upstream deleted, issue #1062)', () => { const name = platformDetector.getExecutableName(); - assert(name.includes('cli-proxy-api-plus')); + const expected = isWindows ? 'cli-proxy-api.exe' : 'cli-proxy-api'; + assert.strictEqual(name, expected); }); }); @@ -94,9 +96,10 @@ describe('Backend Selection', () => { assert(url.includes('router-for-me/CLIProxyAPIPlus/releases')); }); - it('defaults to plus backend', () => { + it('defaults to original backend (Plus upstream deleted, issue #1062)', () => { const url = platformDetector.getDownloadUrl(); - assert(url.includes('CLIProxyAPIPlus')); + assert(url.includes('router-for-me/CLIProxyAPI/releases')); + assert(!url.includes('CLIProxyAPIPlus')); }); }); diff --git a/tests/unit/cliproxy/binary-manager-install.test.ts b/tests/unit/cliproxy/binary-manager-install.test.ts index 92140f1d..4b7d686d 100644 --- a/tests/unit/cliproxy/binary-manager-install.test.ts +++ b/tests/unit/cliproxy/binary-manager-install.test.ts @@ -78,7 +78,7 @@ describe('installCliproxyVersion', () => { skipAutoUpdate: true, }) ).rejects.toThrow( - 'CLIProxy Plus binary is not installed locally. Run "ccs cliproxy install" when you have network access.' + 'CLIProxy binary is not installed locally. Run "ccs cliproxy install" when you have network access.' ); }); });