mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-26 23:56:02 +08:00
8b3ad9caf9
Adds a new ClaudeDesktop AppType that writes Claude Desktop's third-party
inference profile under configLibrary/, sharing _meta.json with other
launchers (Ollama-compatible) so cc-switch can coexist with them.
Two switch modes:
- direct: provider already exposes claude-* / anthropic/claude-* model
ids on Anthropic Messages, Claude Desktop connects to it directly.
- proxy: cc-switch's local proxy acts as the inference gateway,
presenting only claude-* route names to Claude Desktop and mapping
them to real upstream models. Required after Anthropic restricted
Claude Desktop to claude-family ids.
Backend:
- New module claude_desktop_config with snapshot/rollback, official seed
bypass, /claude-desktop/v1/{models,messages} routes, and a single
source of truth for default proxy routes.
- Gateway token persisted in SQLite, validated on every proxied request.
- get_claude_desktop_status surfaces drift signals (stale models,
missing routes, proxy stopped, base URL mismatch, missing token).
Frontend:
- Slim ClaudeDesktopProviderForm independent from ProviderForm,
controlled by a top-level appId guard.
- ProviderList banner consumes the status query (5s polling) and
renders actionable diagnostics.
- ClaudeDesktopRouteToggle in the header to start/stop the local
gateway without touching takeover state.
- Three-locale i18n synchronised.
141 lines
3.2 KiB
TypeScript
141 lines
3.2 KiB
TypeScript
export interface ProxyConfig {
|
|
listen_address: string;
|
|
listen_port: number;
|
|
max_retries: number;
|
|
request_timeout: number;
|
|
enable_logging: boolean;
|
|
live_takeover_active?: boolean;
|
|
// 超时配置
|
|
streaming_first_byte_timeout: number;
|
|
streaming_idle_timeout: number;
|
|
non_streaming_timeout: number;
|
|
}
|
|
|
|
export interface ProxyStatus {
|
|
running: boolean;
|
|
address: string;
|
|
port: number;
|
|
active_connections: number;
|
|
total_requests: number;
|
|
success_requests: number;
|
|
failed_requests: number;
|
|
success_rate: number;
|
|
uptime_seconds: number;
|
|
current_provider: string | null;
|
|
current_provider_id: string | null;
|
|
last_request_at: string | null;
|
|
last_error: string | null;
|
|
failover_count: number;
|
|
active_targets?: ActiveTarget[];
|
|
}
|
|
|
|
export interface ActiveTarget {
|
|
app_type: string;
|
|
provider_name: string;
|
|
provider_id: string;
|
|
}
|
|
|
|
export interface ProxyServerInfo {
|
|
address: string;
|
|
port: number;
|
|
started_at: string;
|
|
}
|
|
|
|
export interface ProxyTakeoverStatus {
|
|
claude: boolean;
|
|
"claude-desktop"?: boolean;
|
|
codex: boolean;
|
|
gemini: boolean;
|
|
opencode: boolean;
|
|
openclaw: boolean;
|
|
hermes: boolean;
|
|
}
|
|
|
|
export interface ProviderHealth {
|
|
provider_id: string;
|
|
app_type: string;
|
|
is_healthy: boolean;
|
|
consecutive_failures: number;
|
|
last_success_at: string | null;
|
|
last_failure_at: string | null;
|
|
last_error: string | null;
|
|
updated_at: string;
|
|
}
|
|
|
|
// 熔断器相关类型
|
|
export interface CircuitBreakerConfig {
|
|
failureThreshold: number;
|
|
successThreshold: number;
|
|
timeoutSeconds: number;
|
|
errorRateThreshold: number;
|
|
minRequests: number;
|
|
}
|
|
|
|
export type CircuitState = "closed" | "open" | "half_open";
|
|
|
|
export interface CircuitBreakerStats {
|
|
state: CircuitState;
|
|
consecutiveFailures: number;
|
|
consecutiveSuccesses: number;
|
|
totalRequests: number;
|
|
failedRequests: number;
|
|
}
|
|
|
|
// 供应商健康状态枚举
|
|
export enum ProviderHealthStatus {
|
|
Healthy = "healthy",
|
|
Degraded = "degraded",
|
|
Failed = "failed",
|
|
Unknown = "unknown",
|
|
}
|
|
|
|
// 扩展 ProviderHealth 以包含前端计算的状态
|
|
export interface ProviderHealthWithStatus extends ProviderHealth {
|
|
status: ProviderHealthStatus;
|
|
circuitState?: CircuitState;
|
|
}
|
|
|
|
export interface ProxyUsageRecord {
|
|
provider_id: string;
|
|
app_type: string;
|
|
endpoint: string;
|
|
request_tokens: number | null;
|
|
response_tokens: number | null;
|
|
status_code: number;
|
|
latency_ms: number;
|
|
error: string | null;
|
|
timestamp: string;
|
|
}
|
|
|
|
// 故障转移队列条目
|
|
export interface FailoverQueueItem {
|
|
providerId: string;
|
|
providerName: string;
|
|
providerNotes?: string;
|
|
sortIndex?: number;
|
|
}
|
|
|
|
// 全局代理配置(统一字段,三行镜像)
|
|
export interface GlobalProxyConfig {
|
|
proxyEnabled: boolean;
|
|
listenAddress: string;
|
|
listenPort: number;
|
|
enableLogging: boolean;
|
|
}
|
|
|
|
// 应用级代理配置(每个 app 独立)
|
|
export interface AppProxyConfig {
|
|
appType: string;
|
|
enabled: boolean;
|
|
autoFailoverEnabled: boolean;
|
|
maxRetries: number;
|
|
streamingFirstByteTimeout: number;
|
|
streamingIdleTimeout: number;
|
|
nonStreamingTimeout: number;
|
|
circuitFailureThreshold: number;
|
|
circuitSuccessThreshold: number;
|
|
circuitTimeoutSeconds: number;
|
|
circuitErrorRateThreshold: number;
|
|
circuitMinRequests: number;
|
|
}
|