From bc10b355a7a507cb8f99f291cbceceba507555c0 Mon Sep 17 00:00:00 2001 From: coso Date: Sat, 20 Dec 2025 15:29:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=87=E6=8D=A2=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E6=B8=85=E7=90=86=20Claude=20?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E5=86=B2=E7=AA=81=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 clean_claude_auth_conflict 函数,切换 Claude 配置时自动移除冲突的 ANTHROPIC_API_KEY - 安装 sonner 并添加 Toaster 组件 - 切换/添加/更新/删除配置时显示成功提示 - 版本更新至 0.14.1 --- package-lock.json | 11 ++++++++++ package.json | 3 ++- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/src/services/live_sync.rs | 32 +++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 +- src/components/ui/sonner.tsx | 20 ++++++++++++++++++ src/hooks/useSwitch.ts | 5 +++++ src/main.tsx | 2 ++ 9 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/components/ui/sonner.tsx diff --git a/package-lock.json b/package-lock.json index fb18b6a49..3e48a06f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "lucide-react": "^0.460.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "sonner": "^2.0.7", "tailwind-merge": "^2.5.4" }, "devDependencies": { @@ -5346,6 +5347,16 @@ "dev": true, "license": "ISC" }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index 37d3cfa78..c6037050c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "proxycast", "private": true, - "version": "0.14.0", + "version": "0.14.1", "type": "module", "repository": { "type": "git", @@ -37,6 +37,7 @@ "lucide-react": "^0.460.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "sonner": "^2.0.7", "tailwind-merge": "^2.5.4" }, "devDependencies": { diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7660bd74f..cb0c72663 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "proxycast" -version = "0.14.0" +version = "0.14.1" dependencies = [ "anyhow", "async-stream", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7750be4e4..27592d4c4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "proxycast" -version = "0.14.0" +version = "0.14.1" description = "AI API Proxy Desktop App" authors = ["you"] edition = "2021" diff --git a/src-tauri/src/services/live_sync.rs b/src-tauri/src/services/live_sync.rs index 34c3bf263..da91bde2f 100644 --- a/src-tauri/src/services/live_sync.rs +++ b/src-tauri/src/services/live_sync.rs @@ -27,6 +27,35 @@ pub fn sync_to_live( } } +/// 清理 Claude 配置中冲突的认证环境变量 +/// +/// Claude Code 同时检测到 ANTHROPIC_AUTH_TOKEN 和 ANTHROPIC_API_KEY 时会报警告。 +/// 此函数确保只保留一个认证变量: +/// - 优先保留 ANTHROPIC_AUTH_TOKEN(OAuth token) +/// - 如果只有 ANTHROPIC_API_KEY,则保留它 +fn clean_claude_auth_conflict(settings: &mut Value) { + if let Some(env) = settings.get_mut("env").and_then(|v| v.as_object_mut()) { + let has_auth_token = env + .get("ANTHROPIC_AUTH_TOKEN") + .and_then(|v| v.as_str()) + .map(|s| !s.is_empty()) + .unwrap_or(false); + let has_api_key = env + .get("ANTHROPIC_API_KEY") + .and_then(|v| v.as_str()) + .map(|s| !s.is_empty()) + .unwrap_or(false); + + // 如果两者都存在,移除 ANTHROPIC_API_KEY(优先使用 AUTH_TOKEN) + if has_auth_token && has_api_key { + tracing::info!( + "检测到 Claude 认证冲突:同时存在 ANTHROPIC_AUTH_TOKEN 和 ANTHROPIC_API_KEY,移除 ANTHROPIC_API_KEY" + ); + env.remove("ANTHROPIC_API_KEY"); + } + } +} + /// Sync Claude settings to ~/.claude/settings.json fn sync_claude_settings( provider: &Provider, @@ -69,6 +98,9 @@ fn sync_claude_settings( settings = provider.settings_config.clone(); } + // 清理冲突的认证环境变量 + clean_claude_auth_conflict(&mut settings); + // Write settings let content = serde_json::to_string_pretty(&settings)?; std::fs::write(&config_path, content)?; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 73f427bed..f136f095f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ProxyCast", - "version": "0.14.0", + "version": "0.14.1", "identifier": "com.proxycast.app", "build": { "beforeDevCommand": "npm run dev", diff --git a/src/components/ui/sonner.tsx b/src/components/ui/sonner.tsx new file mode 100644 index 000000000..28f2d29cb --- /dev/null +++ b/src/components/ui/sonner.tsx @@ -0,0 +1,20 @@ +import { Toaster as SonnerToaster } from "sonner"; + +export function Toaster() { + return ( + + ); +} diff --git a/src/hooks/useSwitch.ts b/src/hooks/useSwitch.ts index dc4f18b88..ee6146018 100644 --- a/src/hooks/useSwitch.ts +++ b/src/hooks/useSwitch.ts @@ -1,4 +1,5 @@ import { useState, useEffect, useCallback } from "react"; +import { toast } from "sonner"; import { switchApi, Provider, AppType } from "@/lib/api/switch"; export function useSwitch(appType: AppType) { @@ -40,21 +41,25 @@ export function useSwitch(appType: AppType) { }; await switchApi.addProvider(newProvider); await fetchProviders(); + toast.success("配置已添加"); }; const updateProvider = async (provider: Provider) => { await switchApi.updateProvider(provider); await fetchProviders(); + toast.success("配置已更新"); }; const deleteProvider = async (id: string) => { await switchApi.deleteProvider(appType, id); await fetchProviders(); + toast.success("配置已删除"); }; const switchToProvider = async (id: string) => { await switchApi.switchProvider(appType, id); await fetchProviders(); + toast.success("切换成功"); }; return { diff --git a/src/main.tsx b/src/main.tsx index 27481e022..326daaa08 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,12 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; +import { Toaster } from "./components/ui/sonner"; import "./index.css"; ReactDOM.createRoot(document.getElementById("root")!).render( + , );