mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-09-24 23:10:56 +08:00
feat: 切换配置时自动清理 Claude 认证冲突并添加操作提示
- 添加 clean_claude_auth_conflict 函数,切换 Claude 配置时自动移除冲突的 ANTHROPIC_API_KEY - 安装 sonner 并添加 Toaster 组件 - 切换/添加/更新/删除配置时显示成功提示 - 版本更新至 0.14.1
This commit is contained in:
Generated
+11
@@ -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",
|
||||
|
||||
+2
-1
@@ -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": {
|
||||
|
||||
Generated
+1
-1
@@ -3367,7 +3367,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proxycast"
|
||||
version = "0.14.0"
|
||||
version = "0.14.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Toaster as SonnerToaster } from "sonner";
|
||||
|
||||
export function Toaster() {
|
||||
return (
|
||||
<SonnerToaster
|
||||
position="top-center"
|
||||
richColors
|
||||
theme="system"
|
||||
toastOptions={{
|
||||
duration: 3000,
|
||||
classNames: {
|
||||
toast:
|
||||
"group rounded-md border bg-background text-foreground shadow-lg",
|
||||
title: "text-sm font-semibold",
|
||||
description: "text-sm text-muted-foreground",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<Toaster />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user