mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 10:21:16 +08:00
chore: bump version to 3.9.0-beta.1
- Update version in package.json, Cargo.toml, tauri.conf.json - Add CHANGELOG entry for v3.9.0-beta.1 with: - Local Proxy Server feature - Auto Failover with circuit breaker - Skills multi-app support - Provider icon colors - 25+ bug fixes - Add proxy feature guide documentation (Chinese)
This commit is contained in:
@@ -5,6 +5,100 @@ All notable changes to CC Switch will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [3.9.0-beta.1] - 2025-12-18
|
||||||
|
|
||||||
|
### Beta Release
|
||||||
|
|
||||||
|
This beta release introduces the **Local API Proxy** feature, along with Skills multi-app support, UI improvements, and numerous bug fixes.
|
||||||
|
|
||||||
|
### Major Features
|
||||||
|
|
||||||
|
#### Local Proxy Server
|
||||||
|
- **Local HTTP Proxy** - High-performance proxy server built on Axum framework
|
||||||
|
- **Multi-app Support** - Unified proxy for Claude Code, Codex, and Gemini CLI API requests
|
||||||
|
- **Per-app Takeover** - Independent control over which apps route through the proxy
|
||||||
|
- **Live Config Takeover** - Automatically backs up and redirects CLI configurations to local proxy
|
||||||
|
|
||||||
|
#### Auto Failover
|
||||||
|
- **Circuit Breaker** - Automatically detects provider failures and triggers protection
|
||||||
|
- **Smart Failover** - Automatically switches to backup provider when current one is unavailable
|
||||||
|
- **Health Tracking** - Real-time monitoring of provider availability
|
||||||
|
- **Independent Failover Queues** - Each app maintains its own failover queue
|
||||||
|
|
||||||
|
#### Monitoring
|
||||||
|
- **Request Logging** - Detailed logging of all proxy requests
|
||||||
|
- **Usage Statistics** - Token consumption, latency, success rate metrics
|
||||||
|
- **Real-time Status** - Frontend displays proxy status and statistics
|
||||||
|
|
||||||
|
#### Skills Multi-App Support
|
||||||
|
- **Multi-app Support** - Skills now support both Claude and Codex (#365)
|
||||||
|
- **Multi-app Migration** - Existing Skills auto-migrate to multi-app structure (#378)
|
||||||
|
- **Installation Path Fix** - Use directory basename for skill installation path (#358)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Provider Icon Colors** - Customize provider icon colors (#385)
|
||||||
|
- **Deeplink Usage Config** - Import usage query config via deeplink (#400)
|
||||||
|
- **Error Request Logging** - Detailed logging for proxy requests (#401)
|
||||||
|
- **Closable Toast** - Added close button to switch notification toast (#350)
|
||||||
|
- **Icon Color Component** - ProviderIcon component supports color prop (#384)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
#### Proxy Related
|
||||||
|
- Takeover Codex base_url via model_provider
|
||||||
|
- Harden crash recovery with fallback detection
|
||||||
|
- Sync UI when active provider differs from current setting
|
||||||
|
- Resolve circuit breaker race condition and error classification
|
||||||
|
- Stabilize live takeover and provider editing
|
||||||
|
- Reset health badges when proxy stops
|
||||||
|
- Retry failover for all HTTP errors including 4xx
|
||||||
|
- Fix HalfOpen counter underflow and config field inconsistencies
|
||||||
|
- Resolve circuit breaker state persistence and HalfOpen deadlock
|
||||||
|
- Auto-recover live config after abnormal exit
|
||||||
|
- Update live backup when hot-switching provider in proxy mode
|
||||||
|
- Wait for server shutdown before exiting app
|
||||||
|
- Disable auto-start on app launch by resetting enabled flag on stop
|
||||||
|
- Sync live config tokens to database before takeover
|
||||||
|
- Resolve 404 error and auto-setup proxy targets
|
||||||
|
|
||||||
|
#### MCP Related
|
||||||
|
- Skip sync when target CLI app is not installed
|
||||||
|
- Improve upsert and import robustness
|
||||||
|
- Use browser-compatible platform detection for MCP presets
|
||||||
|
|
||||||
|
#### UI Related
|
||||||
|
- Restore fade transition for Skills button
|
||||||
|
- Add close button to all success toasts
|
||||||
|
- Prevent card jitter when health badge appears
|
||||||
|
- Update SettingsPage tab styles (#342)
|
||||||
|
|
||||||
|
#### Other
|
||||||
|
- Fix Azure website link (#407)
|
||||||
|
- Add fallback to provider config for usage credentials (#360)
|
||||||
|
- Fix Windows black screen on startup (use system titlebar)
|
||||||
|
- Add fallback for crypto.randomUUID() on older WebViews
|
||||||
|
- Use correct npm package for Codex CLI version check
|
||||||
|
- Security fixes for JavaScript executor and usage script (#151)
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- **Proxy Active Theme** - Apply emerald theme when proxy takeover is active
|
||||||
|
- **Card Animation** - Improved provider card hover animation
|
||||||
|
- **Remove Restart Prompt** - No longer prompts restart when switching providers
|
||||||
|
|
||||||
|
### Technical
|
||||||
|
- Implement per-app takeover mode
|
||||||
|
- Proxy module contains 20+ Rust files with complete layered architecture
|
||||||
|
- Add 5 new database tables for proxy functionality
|
||||||
|
- Modularize handlers.rs to reduce code duplication
|
||||||
|
- Remove is_proxy_target in favor of failover_queue
|
||||||
|
|
||||||
|
### Stats
|
||||||
|
- 55 commits since v3.8.2
|
||||||
|
- 164 files changed
|
||||||
|
- +22,164 / -570 lines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [3.8.0] - 2025-11-28
|
## [3.8.0] - 2025-11-28
|
||||||
|
|
||||||
### Major Updates
|
### Major Updates
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# CC Switch 代理功能使用指南
|
||||||
|
|
||||||
|
## 功能介绍
|
||||||
|
|
||||||
|
CC Switch 的代理功能是一个本地 HTTP 代理服务器,可以统一管理 Claude Code、Codex 和 Gemini CLI 的 API 请求。主要特性包括:
|
||||||
|
|
||||||
|
- **统一代理入口** - 所有 CLI 应用的请求通过本地代理转发
|
||||||
|
- **自动故障转移** - 当前供应商故障时自动切换到备用供应商
|
||||||
|
- **按应用控制** - 可独立控制每个应用是否启用代理
|
||||||
|
- **配置保护** - 自动备份原始配置,停止代理时安全恢复
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 启动代理
|
||||||
|
|
||||||
|
在 CC Switch 主界面,点击右上角的 **Proxy** 按钮,可以看到代理控制面板。
|
||||||
|
|
||||||
|
点击 **启动代理** 按钮启动本地代理服务器。代理默认监听 `127.0.0.1:15721`。
|
||||||
|
|
||||||
|
### 2. 启用应用接管
|
||||||
|
|
||||||
|
代理启动后,你可以选择让哪些应用的请求通过代理:
|
||||||
|
|
||||||
|
- **Claude** - 接管 Claude Code 的 API 请求
|
||||||
|
- **Codex** - 接管 Codex CLI 的 API 请求
|
||||||
|
- **Gemini** - 接管 Gemini CLI 的 API 请求
|
||||||
|
|
||||||
|
点击对应应用的开关即可启用/禁用接管。
|
||||||
|
|
||||||
|
> **注意**:启用接管后,CC Switch 会自动修改对应应用的配置文件,将 API 端点指向本地代理。原始配置会被安全备份。
|
||||||
|
|
||||||
|
### 3. 正常使用 CLI
|
||||||
|
|
||||||
|
启用接管后,你可以正常使用各个 CLI 工具。所有请求都会经过 CC Switch 代理转发到配置的供应商。
|
||||||
|
|
||||||
|
### 4. 停止代理
|
||||||
|
|
||||||
|
当你不再需要代理时,点击 **停止代理** 按钮。CC Switch 会:
|
||||||
|
|
||||||
|
1. 安全关闭代理服务器
|
||||||
|
2. 自动恢复所有应用的原始配置
|
||||||
|
3. 清除代理状态
|
||||||
|
|
||||||
|
## 自动故障转移
|
||||||
|
|
||||||
|
### 工作原理
|
||||||
|
|
||||||
|
代理功能内置了智能故障转移机制:
|
||||||
|
|
||||||
|
1. **健康监控** - 实时监控每个供应商的响应状态
|
||||||
|
2. **熔断器** - 连续失败 5 次后触发熔断,暂停使用该供应商
|
||||||
|
3. **自动切换** - 熔断后自动切换到列表中的下一个供应商
|
||||||
|
4. **自动恢复** - 30 秒后尝试恢复熔断的供应商
|
||||||
|
|
||||||
|
### 配置故障转移
|
||||||
|
|
||||||
|
要使用故障转移功能,你需要:
|
||||||
|
|
||||||
|
1. 在对应应用下添加多个供应商(至少 2 个)
|
||||||
|
2. 启动代理并启用接管
|
||||||
|
3. 当主供应商故障时,代理会自动切换到备用供应商
|
||||||
|
|
||||||
|
### 健康状态指示
|
||||||
|
|
||||||
|
在供应商卡片上可以看到健康状态指示:
|
||||||
|
|
||||||
|
- **绿色** - 供应商正常
|
||||||
|
- **红色** - 供应商故障/熔断中
|
||||||
|
- **灰色** - 未使用代理或未检测
|
||||||
|
|
||||||
|
## 按应用接管
|
||||||
|
|
||||||
|
v3.9.0 新增了按应用分粒度控制功能:
|
||||||
|
|
||||||
|
- 你可以只接管 Claude,而让 Codex 使用原始配置
|
||||||
|
- 每个应用的接管状态独立管理
|
||||||
|
- 启用/禁用不会影响其他应用
|
||||||
|
|
||||||
|
### 接管状态检测
|
||||||
|
|
||||||
|
CC Switch 通过检测配置备份来判断接管状态:
|
||||||
|
|
||||||
|
- 存在备份 = 已接管
|
||||||
|
- 无备份 = 未接管
|
||||||
|
|
||||||
|
这确保了即使 CC Switch 异常退出,重新启动后也能正确识别状态。
|
||||||
|
|
||||||
|
## 代理配置
|
||||||
|
|
||||||
|
在代理面板中,你可以配置以下参数:
|
||||||
|
|
||||||
|
| 参数 | 默认值 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| 监听地址 | 127.0.0.1 | 代理服务器绑定地址 |
|
||||||
|
| 监听端口 | 15721 | 代理服务器端口 |
|
||||||
|
| 最大重试 | 3 | 请求失败时的最大重试次数 |
|
||||||
|
| 请求超时 | 120 秒 | 单个请求的超时时间 |
|
||||||
|
| 启用日志 | 是 | 是否记录请求日志 |
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 代理启动失败,提示端口被占用?
|
||||||
|
|
||||||
|
A: 默认端口 15721 可能被其他程序占用。你可以:
|
||||||
|
- 关闭占用该端口的程序
|
||||||
|
- 在代理配置中修改端口号
|
||||||
|
|
||||||
|
### Q: 启用接管后 CLI 无法使用?
|
||||||
|
|
||||||
|
A: 请检查:
|
||||||
|
1. 代理服务器是否正常运行(查看代理面板状态)
|
||||||
|
2. 供应商配置是否正确(API Key 等)
|
||||||
|
3. 网络连接是否正常
|
||||||
|
|
||||||
|
### Q: 如何恢复原始配置?
|
||||||
|
|
||||||
|
A: 点击 **停止代理** 按钮,CC Switch 会自动恢复所有应用的原始配置。
|
||||||
|
|
||||||
|
如果 CC Switch 异常退出,重新启动后会检测到之前的备份,你可以:
|
||||||
|
- 点击停止代理来恢复配置
|
||||||
|
- 或继续使用代理功能
|
||||||
|
|
||||||
|
### Q: 故障转移没有生效?
|
||||||
|
|
||||||
|
A: 请确保:
|
||||||
|
1. 配置了至少 2 个供应商
|
||||||
|
2. 代理已启动且接管已启用
|
||||||
|
3. 故障转移只在代理模式下工作
|
||||||
|
|
||||||
|
### Q: 代理会影响性能吗?
|
||||||
|
|
||||||
|
A: 本地代理的延迟开销非常小(通常 < 1ms)。但如果启用了请求日志,在高频请求场景下可能会有少量性能影响。
|
||||||
|
|
||||||
|
## 技术细节
|
||||||
|
|
||||||
|
### 配置文件位置
|
||||||
|
|
||||||
|
启用接管后,CC Switch 会修改以下配置文件:
|
||||||
|
|
||||||
|
| 应用 | 配置文件 | 修改内容 |
|
||||||
|
|------|----------|----------|
|
||||||
|
| Claude | `~/.claude/settings.json` | `apiBaseUrl` 指向代理 |
|
||||||
|
| Codex | `~/.codex/config.toml` | `[api] baseUrl` 指向代理 |
|
||||||
|
| Gemini | `~/.gemini/.env` | `GEMINI_BASE_URL` 指向代理 |
|
||||||
|
|
||||||
|
原始配置备份在 CC Switch 数据库中,停止代理时自动恢复。
|
||||||
|
|
||||||
|
### 代理模式
|
||||||
|
|
||||||
|
代理服务器运行在接管模式下,会:
|
||||||
|
|
||||||
|
1. 接收来自 CLI 的 HTTPS 请求
|
||||||
|
2. 根据当前供应商配置转发到真实 API 端点
|
||||||
|
3. 返回响应给 CLI
|
||||||
|
4. 记录请求日志和健康状态
|
||||||
|
|
||||||
|
### 数据库表
|
||||||
|
|
||||||
|
代理功能使用以下数据库表:
|
||||||
|
|
||||||
|
- `proxy_config` - 代理配置
|
||||||
|
- `provider_health` - 供应商健康状态
|
||||||
|
- `proxy_request_logs` - 请求日志
|
||||||
|
- `circuit_breaker_config` - 熔断器配置
|
||||||
|
- `proxy_live_backup` - Live 配置备份
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cc-switch",
|
"name": "cc-switch",
|
||||||
"version": "3.8.2",
|
"version": "3.9.0-beta.1",
|
||||||
"description": "All-in-One Assistant for Claude Code, Codex & Gemini CLI",
|
"description": "All-in-One Assistant for Claude Code, Codex & Gemini CLI",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm tauri dev",
|
"dev": "pnpm tauri dev",
|
||||||
|
|||||||
Generated
+1
-1
@@ -695,7 +695,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc-switch"
|
name = "cc-switch"
|
||||||
version = "3.8.2"
|
version = "3.9.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cc-switch"
|
name = "cc-switch"
|
||||||
version = "3.8.2"
|
version = "3.9.0-beta.1"
|
||||||
description = "All-in-One Assistant for Claude Code, Codex & Gemini CLI"
|
description = "All-in-One Assistant for Claude Code, Codex & Gemini CLI"
|
||||||
authors = ["Jason Young"]
|
authors = ["Jason Young"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "CC Switch",
|
"productName": "CC Switch",
|
||||||
"version": "3.8.2",
|
"version": "3.9.0-beta.1",
|
||||||
"identifier": "com.ccswitch.desktop",
|
"identifier": "com.ccswitch.desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../dist",
|
"frontendDist": "../dist",
|
||||||
|
|||||||
@@ -19,13 +19,8 @@ interface ProxyToggleProps {
|
|||||||
|
|
||||||
export function ProxyToggle({ className, activeApp }: ProxyToggleProps) {
|
export function ProxyToggle({ className, activeApp }: ProxyToggleProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const { isRunning, takeoverStatus, setTakeoverForApp, isPending, status } =
|
||||||
isRunning,
|
useProxyStatus();
|
||||||
takeoverStatus,
|
|
||||||
setTakeoverForApp,
|
|
||||||
isPending,
|
|
||||||
status,
|
|
||||||
} = useProxyStatus();
|
|
||||||
|
|
||||||
const handleToggle = async (checked: boolean) => {
|
const handleToggle = async (checked: boolean) => {
|
||||||
await setTakeoverForApp({ appType: activeApp, enabled: checked });
|
await setTakeoverForApp({ appType: activeApp, enabled: checked });
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function generateThirdPartyAuth(apiKey: string): Record<string, any> {
|
|||||||
export function generateThirdPartyConfig(
|
export function generateThirdPartyConfig(
|
||||||
providerName: string,
|
providerName: string,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
modelName = "gpt-5.1-codex"
|
modelName = "gpt-5.1-codex",
|
||||||
): string {
|
): string {
|
||||||
// 清理供应商名称,确保符合TOML键名规范
|
// 清理供应商名称,确保符合TOML键名规范
|
||||||
const cleanProviderName =
|
const cleanProviderName =
|
||||||
@@ -113,7 +113,7 @@ requires_openai_auth = true`,
|
|||||||
config: generateThirdPartyConfig(
|
config: generateThirdPartyConfig(
|
||||||
"aihubmix",
|
"aihubmix",
|
||||||
"https://aihubmix.com/v1",
|
"https://aihubmix.com/v1",
|
||||||
"gpt-5.1-codex"
|
"gpt-5.1-codex",
|
||||||
),
|
),
|
||||||
endpointCandidates: [
|
endpointCandidates: [
|
||||||
"https://aihubmix.com/v1",
|
"https://aihubmix.com/v1",
|
||||||
@@ -128,7 +128,7 @@ requires_openai_auth = true`,
|
|||||||
config: generateThirdPartyConfig(
|
config: generateThirdPartyConfig(
|
||||||
"dmxapi",
|
"dmxapi",
|
||||||
"https://www.dmxapi.cn/v1",
|
"https://www.dmxapi.cn/v1",
|
||||||
"gpt-5.1-codex"
|
"gpt-5.1-codex",
|
||||||
),
|
),
|
||||||
endpointCandidates: ["https://www.dmxapi.cn/v1"],
|
endpointCandidates: ["https://www.dmxapi.cn/v1"],
|
||||||
},
|
},
|
||||||
@@ -141,7 +141,7 @@ requires_openai_auth = true`,
|
|||||||
config: generateThirdPartyConfig(
|
config: generateThirdPartyConfig(
|
||||||
"packycode",
|
"packycode",
|
||||||
"https://www.packyapi.com/v1",
|
"https://www.packyapi.com/v1",
|
||||||
"gpt-5.1-codex"
|
"gpt-5.1-codex",
|
||||||
),
|
),
|
||||||
endpointCandidates: [
|
endpointCandidates: [
|
||||||
"https://www.packyapi.com/v1",
|
"https://www.packyapi.com/v1",
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { ProxyStatus, ProxyServerInfo, ProxyTakeoverStatus } from "@/types/proxy";
|
import type {
|
||||||
|
ProxyStatus,
|
||||||
|
ProxyServerInfo,
|
||||||
|
ProxyTakeoverStatus,
|
||||||
|
} from "@/types/proxy";
|
||||||
import { extractErrorMessage } from "@/utils/errorUtils";
|
import { extractErrorMessage } from "@/utils/errorUtils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,13 +86,8 @@ export function useProxyStatus() {
|
|||||||
|
|
||||||
// 按应用开启/关闭接管
|
// 按应用开启/关闭接管
|
||||||
const setTakeoverForAppMutation = useMutation({
|
const setTakeoverForAppMutation = useMutation({
|
||||||
mutationFn: ({
|
mutationFn: ({ appType, enabled }: { appType: string; enabled: boolean }) =>
|
||||||
appType,
|
invoke("set_proxy_takeover_for_app", { appType, enabled }),
|
||||||
enabled,
|
|
||||||
}: {
|
|
||||||
appType: string;
|
|
||||||
enabled: boolean;
|
|
||||||
}) => invoke("set_proxy_takeover_for_app", { appType, enabled }),
|
|
||||||
onSuccess: (_data, variables) => {
|
onSuccess: (_data, variables) => {
|
||||||
const appLabel =
|
const appLabel =
|
||||||
variables.appType === "claude"
|
variables.appType === "claude"
|
||||||
|
|||||||
Reference in New Issue
Block a user