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(
+
,
);