mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 10:16:49 +00:00
224 lines
5.9 KiB
TypeScript
224 lines
5.9 KiB
TypeScript
/**
|
|
* CLIProxy Binary Service
|
|
*
|
|
* Handles CLIProxyAPI binary version management:
|
|
* - Get current version status
|
|
* - Install specific versions
|
|
* - Install latest version
|
|
* - Version pinning
|
|
*/
|
|
|
|
import {
|
|
getInstalledCliproxyVersion,
|
|
installCliproxyVersion,
|
|
fetchLatestCliproxyVersion,
|
|
isCLIProxyInstalled,
|
|
getCLIProxyPath,
|
|
getPinnedVersion,
|
|
savePinnedVersion,
|
|
clearPinnedVersion,
|
|
isVersionPinned,
|
|
resolveLocalBackend,
|
|
} from '../binary-manager';
|
|
import { BACKEND_CONFIG, DEFAULT_BACKEND } from '../platform-detector';
|
|
import { CLIProxyBackend } from '../types';
|
|
import { loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
|
|
|
|
/** Binary status result */
|
|
export interface BinaryStatusResult {
|
|
installed: boolean;
|
|
currentVersion: string | null;
|
|
pinnedVersion: string | null;
|
|
binaryPath: string;
|
|
fallbackVersion: string;
|
|
backend: CLIProxyBackend;
|
|
}
|
|
|
|
/** Install result */
|
|
export interface InstallResult {
|
|
success: boolean;
|
|
version: string;
|
|
error?: string;
|
|
wasPinned?: boolean;
|
|
}
|
|
|
|
/** Latest version check result */
|
|
export interface LatestVersionResult {
|
|
success: boolean;
|
|
latestVersion?: string;
|
|
currentVersion?: string;
|
|
updateAvailable?: boolean;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Get current binary status for a specific backend
|
|
*/
|
|
export function getBinaryStatus(backend?: CLIProxyBackend): BinaryStatusResult {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
const backendConfig = BACKEND_CONFIG[effectiveBackend];
|
|
return {
|
|
installed: isCLIProxyInstalled(effectiveBackend),
|
|
currentVersion: getInstalledCliproxyVersion(effectiveBackend),
|
|
pinnedVersion: getPinnedVersion(effectiveBackend),
|
|
binaryPath: getCLIProxyPath(effectiveBackend),
|
|
fallbackVersion: backendConfig.fallbackVersion,
|
|
backend: effectiveBackend,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Check for latest version
|
|
*/
|
|
export async function checkLatestVersion(backend?: CLIProxyBackend): Promise<LatestVersionResult> {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
|
|
try {
|
|
// Use checkCliproxyUpdate which is backend-aware (uses correct GitHub repo)
|
|
const { checkCliproxyUpdate } = await import('../binary-manager');
|
|
const updateResult = await checkCliproxyUpdate(effectiveBackend);
|
|
const latestVersion = updateResult.latestVersion;
|
|
const currentVersion = getInstalledCliproxyVersion(effectiveBackend);
|
|
const updateAvailable = latestVersion !== currentVersion;
|
|
|
|
return {
|
|
success: true,
|
|
latestVersion,
|
|
currentVersion: currentVersion || undefined,
|
|
updateAvailable,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
success: false,
|
|
error: (error as Error).message,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate version format (supports X.Y.Z or X.Y.Z-N suffix)
|
|
*/
|
|
export function isValidVersionFormat(version: string): boolean {
|
|
return /^\d+\.\d+\.\d+(-\d+)?$/.test(version);
|
|
}
|
|
|
|
/**
|
|
* Install a specific version and pin it
|
|
*/
|
|
export async function installVersion(
|
|
version: string,
|
|
verbose = false,
|
|
backend?: CLIProxyBackend
|
|
): Promise<InstallResult> {
|
|
if (!isValidVersionFormat(version)) {
|
|
return {
|
|
success: false,
|
|
version,
|
|
error: 'Invalid version format. Expected format: X.Y.Z (e.g., 6.5.53)',
|
|
};
|
|
}
|
|
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
|
|
try {
|
|
await installCliproxyVersion(version, verbose, effectiveBackend);
|
|
savePinnedVersion(version, effectiveBackend);
|
|
|
|
return {
|
|
success: true,
|
|
version,
|
|
wasPinned: true,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
success: false,
|
|
version,
|
|
error: (error as Error).message,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Install latest version and clear any pin
|
|
*/
|
|
export async function installLatest(
|
|
verbose = false,
|
|
backend?: CLIProxyBackend
|
|
): Promise<InstallResult> {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
|
|
try {
|
|
const latestVersion = await fetchLatestCliproxyVersion(effectiveBackend);
|
|
const currentVersion = getInstalledCliproxyVersion(effectiveBackend);
|
|
const wasPinned = isVersionPinned(effectiveBackend);
|
|
|
|
if (isCLIProxyInstalled(effectiveBackend) && latestVersion === currentVersion && !wasPinned) {
|
|
return {
|
|
success: true,
|
|
version: latestVersion,
|
|
error: `Already running latest version: v${latestVersion}`,
|
|
};
|
|
}
|
|
|
|
await installCliproxyVersion(latestVersion, verbose, effectiveBackend);
|
|
clearPinnedVersion(effectiveBackend);
|
|
|
|
return {
|
|
success: true,
|
|
version: latestVersion,
|
|
wasPinned,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
success: false,
|
|
version: '',
|
|
error: (error as Error).message,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a version is pinned
|
|
*/
|
|
export function isPinned(backend?: CLIProxyBackend): boolean {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
return isVersionPinned(effectiveBackend);
|
|
}
|
|
|
|
/**
|
|
* Get pinned version if any
|
|
*/
|
|
export function getPinned(backend?: CLIProxyBackend): string | null {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
return getPinnedVersion(effectiveBackend);
|
|
}
|
|
|
|
/**
|
|
* Clear version pin
|
|
*/
|
|
export function clearPin(backend?: CLIProxyBackend): void {
|
|
const effectiveBackend = resolveLocalBackend(
|
|
backend ?? loadOrCreateUnifiedConfig().cliproxy?.backend ?? DEFAULT_BACKEND,
|
|
{ warnOnFallback: true }
|
|
);
|
|
clearPinnedVersion(effectiveBackend);
|
|
}
|