mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 20:17:45 +00:00
b454834175
* fix(version): show active config path instead of deprecated config.json The version command was using deprecated getConfigPath() which always returned config.json path. Now uses getActiveConfigPath() which shows config.yaml in unified mode or config.json in legacy mode. * chore(release): 7.37.1-dev.1 [skip ci] * fix(ui): use native dynamic import to fix Node 24 ESM/CJS interop TypeScript compiles import() to require() when targeting CommonJS, which breaks ESM packages like ora on Node 24. Use new Function() to create native dynamic import at runtime, bypassing TS transform. Closes #472 * chore(release): 7.37.1-dev.2 [skip ci] * fix(env): strip ANTHROPIC_* from account/default profiles Account and default profiles inherit process.env which may contain stale ANTHROPIC_BASE_URL from prior CLIProxy sessions. This causes ConnectionRefused errors when Claude tries to hit an unavailable proxy. Settings-based profiles already handle this by explicitly injecting their own ANTHROPIC_* values. This fix applies the same protection to account/default profiles by stripping ANTHROPIC_* before spawn. Closes #474 * test(env): add unit tests for stripAnthropicEnv Address code review feedback from PR #475. Tests cover: - Removing all ANTHROPIC_* keys - Preserving non-ANTHROPIC keys - Empty object handling - Undefined value preservation - Case sensitivity (only uppercase ANTHROPIC_) - All ANTHROPIC_ prefixed variants stripped * chore(release): 7.37.1-dev.3 [skip ci] * feat(cliproxy): add extended context support for 1M token window Add --1m and --no-1m flags to enable/disable 1M token context window. Uses Claude Code's [1m] suffix mechanism. Behavior: - Gemini models: auto-enabled by default - Claude models: opt-in with --1m flag - New extendedContext field in model catalog Also adds Claude Opus 4.6 to model catalog with extended context support. Closes #103 * feat(ui): add extended context toggle in dashboard model config - Add ExtendedContextToggle component for 1M token context window - Add Claude Opus 4.6 (claude-opus-4-6-20260203) to model catalogs - Mark Gemini and Claude models with extendedContext: true - Toggle only appears when selected model supports extended context - Auto-enabled info for native Gemini, opt-in info for Claude Part of extended context feature implementation for issue #103. * fix: address code review findings and CI failure - Fix CI error: add missing 'provider' prop to ModelConfigSection - Fix case sensitivity in applyExtendedContextSuffix - Fix whitespace handling in stripModelSuffixes - Handle --1m=value and --no-1m=value CLI patterns - Add warning when --1m used on unsupported model - Sync agy catalog: add extendedContext to gemini-3-pro-preview - Extract isNativeGeminiModel to shared utility (DRY) - Add 21 unit tests for extended-context-config * fix(catalog): rename claude-opus-4-6-20260203 to claude-opus-4-6 * fix(ui): wire extended context toggle through component tree - Add extendedContextEnabled and toggleExtendedContext to useProviderEditor hook - Store setting as CCS_EXTENDED_CONTEXT env var in provider settings - Pass props through provider-editor → model-config-tab → model-config-section - Update UseProviderEditorReturn type with new properties * fix(ui): apply [1m] suffix directly to model strings in settings - Toggle now applies/strips [1m] suffix to all ANTHROPIC_*MODEL env vars - Extended context detected by checking if any model has [1m] suffix - Remove legacy CCS_EXTENDED_CONTEXT flag approach - Add suffix utilities: applyExtendedContextSuffix, stripExtendedContextSuffix - Raw Configuration now shows actual model values with [1m] suffix * fix(qwen): update model catalog with correct context windows and tier mappings - Update context window specs from official Alibaba docs: - Qwen3 Coder Plus: 1M context (was 32K) - Qwen3 Max: 256K context (flagship) - Qwen3 Coder Flash: fast code generation - Fix preset mappings for Claude tier equivalence: - Opus → qwen3-max (flagship 256K) - Sonnet → qwen3-coder-plus (balanced 1M) - Haiku → qwen3-coder-flash (fast) - Update provider descriptions to reflect 256K-1M context range - Add all 7 Qwen models from CLIProxyAPI: qwen3-coder-plus, qwen3-max, qwen3-max-preview, qwen3-235b, qwen3-vl-plus, qwen3-coder-flash, qwen3-32b Closes #478 * fix(ui): only apply [1m] suffix to ANTHROPIC_MODEL, fix toggle refresh - Only ANTHROPIC_MODEL gets [1m] suffix, not tier mappings - Strip [1m] when looking up model in catalog to prevent toggle disappearing - Fix odd page refresh when toggling extended context * chore(release): 7.37.1-dev.4 [skip ci] * fix(ui): remove duplicate import in use-provider-editor * chore: address PR review feedback - sync comment and unused import * chore(release): 7.37.1-dev.5 [skip ci] * feat(cliproxy): add Opus 4.6 to Antigravity model catalog (#482) * feat(cliproxy): add Opus 4.6 to Antigravity model catalog - Add gemini-claude-opus-4-6-thinking as new default agy model - Update preset mappings to route opus tier to Opus 4.6 - Bump CLIProxy fallback versions to v6.8.2 - Keep Opus 4.5 as previous flagship option * fix(cliproxy): include oauth-model-alias in config generation Root cause: CLIProxy config.yaml was missing Opus 4.6 alias because: 1. CLIProxyPlus startup migration is disabled (intentional) 2. CCS config generator never wrote oauth-model-alias section 3. Existing users with outdated aliases got 502 on Opus 4.6 Fix: - Add DEFAULT_ANTIGRAVITY_ALIASES to config generator - Generate oauth-model-alias section in config.yaml template - Preserve claude-api-key and custom aliases during regeneration - Bump config version to v6 to trigger auto-regeneration - Update model catalog tests for new model count * fix(cliproxy): preserve YAML indentation in extractYamlSection - Replace .trim() with regex to strip only leading/trailing newlines, preserving 2-space indent on claude-api-key children - Skip standalone comments at col 0 in section boundary detection - Update stale test description (4 → 5 models) * chore(release): 7.37.1-dev.6 [skip ci] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
/**
|
|
* Platform Detector for CLIProxyAPI Binary Downloads
|
|
*
|
|
* Detects OS and architecture to determine correct binary asset.
|
|
* Supports 6 platforms: darwin/linux/windows x amd64/arm64
|
|
*/
|
|
|
|
import {
|
|
PlatformInfo,
|
|
SupportedOS,
|
|
SupportedArch,
|
|
ArchiveExtension,
|
|
CLIProxyBackend,
|
|
} from './types';
|
|
|
|
/** Backend configuration */
|
|
export const BACKEND_CONFIG = {
|
|
original: {
|
|
repo: 'router-for-me/CLIProxyAPI',
|
|
binaryPrefix: 'CLIProxyAPI',
|
|
executable: 'cli-proxy-api',
|
|
fallbackVersion: '6.8.2',
|
|
},
|
|
plus: {
|
|
repo: 'router-for-me/CLIProxyAPIPlus',
|
|
binaryPrefix: 'CLIProxyAPIPlus',
|
|
executable: 'cli-proxy-api-plus',
|
|
fallbackVersion: '6.8.2-0',
|
|
},
|
|
} as const;
|
|
|
|
/** Default backend */
|
|
export const DEFAULT_BACKEND: CLIProxyBackend = 'plus';
|
|
|
|
/**
|
|
* CLIProxyAPIPlus fallback version (used when GitHub API unavailable)
|
|
* Auto-update fetches latest from GitHub; this is only a safety net
|
|
* Note: CLIProxyAPIPlus uses v6.6.X-0 suffix pattern
|
|
* @deprecated Use getFallbackVersion() or BACKEND_CONFIG instead
|
|
*/
|
|
export const CLIPROXY_FALLBACK_VERSION = BACKEND_CONFIG[DEFAULT_BACKEND].fallbackVersion;
|
|
|
|
/**
|
|
* Maximum stable version cap - prevents auto-update to known unstable releases
|
|
* Currently set high since v89+ are all stable.
|
|
* Only v81-88 have known bugs (see CLIPROXY_FAULTY_RANGE).
|
|
* See: https://github.com/kaitranntt/ccs/issues/269
|
|
*/
|
|
export const CLIPROXY_MAX_STABLE_VERSION = '9.9.999-0';
|
|
|
|
/**
|
|
* Faulty version range - versions with known critical bugs
|
|
* v81-88 have context cancellation bugs causing intermittent 500 errors
|
|
* v89 confirmed stable
|
|
*/
|
|
export const CLIPROXY_FAULTY_RANGE = { min: '6.6.81-0', max: '6.6.88-0' };
|
|
|
|
/** @deprecated Use CLIPROXY_FALLBACK_VERSION instead */
|
|
export const CLIPROXY_VERSION = CLIPROXY_FALLBACK_VERSION;
|
|
|
|
/**
|
|
* Platform mapping from Node.js values to CLIProxyAPI naming
|
|
*/
|
|
const OS_MAP: Record<string, SupportedOS | undefined> = {
|
|
darwin: 'darwin',
|
|
linux: 'linux',
|
|
win32: 'windows',
|
|
};
|
|
|
|
const ARCH_MAP: Record<string, SupportedArch | undefined> = {
|
|
x64: 'amd64',
|
|
arm64: 'arm64',
|
|
};
|
|
|
|
/**
|
|
* Detect current platform and return binary info
|
|
* @param version Optional version for binaryName (defaults to backend fallback)
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @throws Error if platform is unsupported
|
|
*/
|
|
export function detectPlatform(
|
|
version?: string,
|
|
backend: CLIProxyBackend = DEFAULT_BACKEND
|
|
): PlatformInfo {
|
|
const nodePlatform = process.platform;
|
|
const nodeArch = process.arch;
|
|
|
|
const os = OS_MAP[nodePlatform];
|
|
const arch = ARCH_MAP[nodeArch];
|
|
|
|
if (!os) {
|
|
throw new Error(
|
|
`Unsupported operating system: ${nodePlatform}\n` +
|
|
`Supported: macOS (darwin), Linux, Windows`
|
|
);
|
|
}
|
|
|
|
if (!arch) {
|
|
throw new Error(
|
|
`Unsupported CPU architecture: ${nodeArch}\n` + `Supported: x64 (amd64), arm64`
|
|
);
|
|
}
|
|
|
|
const config = BACKEND_CONFIG[backend];
|
|
const ver = version || config.fallbackVersion;
|
|
const extension: ArchiveExtension = os === 'windows' ? 'zip' : 'tar.gz';
|
|
const binaryName = `${config.binaryPrefix}_${ver}_${os}_${arch}.${extension}`;
|
|
|
|
return {
|
|
os,
|
|
arch,
|
|
binaryName,
|
|
extension,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get executable name based on platform
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @returns Binary executable name (with .exe on Windows)
|
|
*/
|
|
export function getExecutableName(backend: CLIProxyBackend = DEFAULT_BACKEND): string {
|
|
const config = BACKEND_CONFIG[backend];
|
|
const platform = detectPlatform(undefined, backend);
|
|
return platform.os === 'windows' ? `${config.executable}.exe` : config.executable;
|
|
}
|
|
|
|
/**
|
|
* Get the name of the binary inside the archive
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @returns Binary name as it appears in the tar.gz/zip
|
|
*/
|
|
export function getArchiveBinaryName(backend: CLIProxyBackend = DEFAULT_BACKEND): string {
|
|
return getExecutableName(backend);
|
|
}
|
|
|
|
/**
|
|
* Get download URL for current platform
|
|
* @param version Version to download (defaults to backend fallback version)
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @returns Full GitHub release download URL
|
|
*/
|
|
export function getDownloadUrl(
|
|
version?: string,
|
|
backend: CLIProxyBackend = DEFAULT_BACKEND
|
|
): string {
|
|
const config = BACKEND_CONFIG[backend];
|
|
const ver = version || config.fallbackVersion;
|
|
const platform = detectPlatform(ver, backend);
|
|
return `https://github.com/${config.repo}/releases/download/v${ver}/${platform.binaryName}`;
|
|
}
|
|
|
|
/**
|
|
* Get checksums.txt URL for version
|
|
* @param version Version to get checksums for (defaults to backend fallback version)
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @returns Full URL to checksums.txt
|
|
*/
|
|
export function getChecksumsUrl(
|
|
version?: string,
|
|
backend: CLIProxyBackend = DEFAULT_BACKEND
|
|
): string {
|
|
const config = BACKEND_CONFIG[backend];
|
|
const ver = version || config.fallbackVersion;
|
|
return `https://github.com/${config.repo}/releases/download/v${ver}/checksums.txt`;
|
|
}
|
|
|
|
/**
|
|
* Get fallback version for backend
|
|
* @param backend Backend variant to use (defaults to DEFAULT_BACKEND)
|
|
* @returns Fallback version string
|
|
*/
|
|
export function getFallbackVersion(backend: CLIProxyBackend = DEFAULT_BACKEND): string {
|
|
return BACKEND_CONFIG[backend].fallbackVersion;
|
|
}
|
|
|
|
/**
|
|
* Check if platform is supported
|
|
* @returns true if current platform is supported
|
|
*/
|
|
export function isPlatformSupported(): boolean {
|
|
try {
|
|
detectPlatform();
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get human-readable platform description
|
|
* @returns Description string (e.g., "macOS arm64")
|
|
*/
|
|
export function getPlatformDescription(): string {
|
|
try {
|
|
const platform = detectPlatform();
|
|
const osName =
|
|
platform.os === 'darwin' ? 'macOS' : platform.os === 'linux' ? 'Linux' : 'Windows';
|
|
return `${osName} ${platform.arch}`;
|
|
} catch {
|
|
return `${process.platform} ${process.arch} (unsupported)`;
|
|
}
|
|
}
|