mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-09-24 23:10:56 +08:00
chore: bump version to 0.17.9
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "proxycast",
|
||||
"private": true,
|
||||
"version": "0.17.8",
|
||||
"version": "0.17.9",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Generated
+1
-1
@@ -3377,7 +3377,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proxycast"
|
||||
version = "0.17.8"
|
||||
version = "0.17.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "proxycast"
|
||||
version = "0.17.8"
|
||||
version = "0.17.9"
|
||||
description = "AI API Proxy Desktop App"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -913,6 +913,30 @@ pub fn add_claude_key_credential(
|
||||
)
|
||||
}
|
||||
|
||||
/// 添加 Gemini API Key 凭证
|
||||
#[tauri::command]
|
||||
pub fn add_gemini_api_key_credential(
|
||||
db: State<'_, DbConnection>,
|
||||
pool_service: State<'_, ProviderPoolServiceState>,
|
||||
api_key: String,
|
||||
base_url: Option<String>,
|
||||
excluded_models: Option<Vec<String>>,
|
||||
name: Option<String>,
|
||||
) -> Result<ProviderCredential, String> {
|
||||
pool_service.0.add_credential(
|
||||
&db,
|
||||
"gemini_api_key",
|
||||
CredentialData::GeminiApiKey {
|
||||
api_key,
|
||||
base_url,
|
||||
excluded_models: excluded_models.unwrap_or_default(),
|
||||
},
|
||||
name,
|
||||
Some(true),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// 添加 Codex OAuth 凭证(通过文件路径)
|
||||
#[tauri::command]
|
||||
pub fn add_codex_oauth_credential(
|
||||
|
||||
@@ -2014,6 +2014,7 @@ pub fn run() {
|
||||
commands::provider_pool_cmd::add_antigravity_oauth_credential,
|
||||
commands::provider_pool_cmd::add_openai_key_credential,
|
||||
commands::provider_pool_cmd::add_claude_key_credential,
|
||||
commands::provider_pool_cmd::add_gemini_api_key_credential,
|
||||
commands::provider_pool_cmd::add_codex_oauth_credential,
|
||||
commands::provider_pool_cmd::add_claude_oauth_credential,
|
||||
commands::provider_pool_cmd::add_iflow_oauth_credential,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "ProxyCast",
|
||||
"version": "0.17.8",
|
||||
"version": "0.17.9",
|
||||
"identifier": "com.proxycast.app",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
@@ -42,10 +42,13 @@ export function AddCredentialModal({
|
||||
// API Key 字段
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
const [baseUrl, setBaseUrl] = useState("");
|
||||
const [excludedModels, setExcludedModels] = useState<string[]>([]);
|
||||
|
||||
// 判断是否为 OAuth 类型(不包括有特殊表单的 antigravity、codex、claude_oauth、qwen、iflow、gemini、kiro)
|
||||
const isSimpleOAuth: string[] = []; // Kiro 现在有自己的表单
|
||||
const isApiKey = ["openai", "claude"].includes(providerType);
|
||||
const isApiKey = ["openai", "claude", "gemini_api_key"].includes(
|
||||
providerType,
|
||||
);
|
||||
|
||||
const handleSelectFile = async () => {
|
||||
try {
|
||||
@@ -197,6 +200,14 @@ export function AddCredentialModal({
|
||||
trimmedName,
|
||||
);
|
||||
break;
|
||||
case "gemini_api_key":
|
||||
await providerPoolApi.addGeminiApiKey(
|
||||
apiKey,
|
||||
baseUrl.trim() || undefined,
|
||||
excludedModels.length > 0 ? excludedModels : undefined,
|
||||
trimmedName,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +295,9 @@ export function AddCredentialModal({
|
||||
placeholder={
|
||||
providerType === "openai"
|
||||
? "https://api.openai.com/v1"
|
||||
: "https://api.anthropic.com/v1"
|
||||
: providerType === "claude"
|
||||
? "https://api.anthropic.com/v1"
|
||||
: "https://generativelanguage.googleapis.com"
|
||||
}
|
||||
className="w-full rounded-lg border bg-background px-3 py-2 text-sm"
|
||||
/>
|
||||
@@ -292,6 +305,31 @@ export function AddCredentialModal({
|
||||
留空使用默认 URL,或输入自定义代理地址
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{providerType === "gemini_api_key" && (
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium">
|
||||
排除模型 (可选)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={excludedModels.join(", ")}
|
||||
onChange={(e) =>
|
||||
setExcludedModels(
|
||||
e.target.value
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s),
|
||||
)
|
||||
}
|
||||
placeholder="gemini-1.5-pro, gemini-1.5-flash..."
|
||||
className="w-full rounded-lg border bg-background px-3 py-2 text-sm"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
用逗号分隔多个模型名称,支持通配符(如 *-preview)
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -60,6 +60,14 @@ const providerModels: Record<PoolProviderType, string[]> = {
|
||||
"claude-sonnet-4-20250514",
|
||||
], // Claude OAuth
|
||||
iflow: ["deepseek-chat", "deepseek-reasoner"], // iFlow
|
||||
gemini_api_key: [
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-flash-lite",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-pro-preview-06-05",
|
||||
"gemini-2.5-flash-preview-09-2025",
|
||||
"gemini-3-pro-preview",
|
||||
], // Gemini API Key
|
||||
};
|
||||
|
||||
export function EditCredentialModal({
|
||||
|
||||
@@ -44,8 +44,8 @@ const oauthProviderTypes: PoolProviderType[] = [
|
||||
// API Key 类型凭证(直接填入 API Key)
|
||||
const apiKeyProviderTypes: PoolProviderType[] = ["openai", "claude"];
|
||||
|
||||
// 配置类型 tab(非凭证池)- gemini_api 移到 API Key 分类下
|
||||
type ConfigTabType = "gemini_api" | "vertex" | "amp";
|
||||
// 配置类型 tab(非凭证池,存储在配置文件中)
|
||||
type ConfigTabType = "vertex" | "amp" | "gemini_api_key";
|
||||
|
||||
// 所有 tab 类型
|
||||
type TabType = PoolProviderType | ConfigTabType;
|
||||
@@ -60,17 +60,18 @@ const providerLabels: Record<PoolProviderType, string> = {
|
||||
codex: "Codex (OAuth / API Key)",
|
||||
claude_oauth: "Claude OAuth",
|
||||
iflow: "iFlow",
|
||||
gemini_api_key: "Gemini",
|
||||
};
|
||||
|
||||
const configTabLabels: Record<ConfigTabType, string> = {
|
||||
gemini_api: "Gemini",
|
||||
vertex: "Vertex AI",
|
||||
amp: "Amp CLI",
|
||||
gemini_api_key: "Gemini API Key",
|
||||
};
|
||||
|
||||
// 判断是否为配置类型 tab
|
||||
const isConfigTab = (tab: TabType): tab is ConfigTabType => {
|
||||
return ["gemini_api", "vertex", "amp"].includes(tab);
|
||||
return ["vertex", "amp", "gemini_api_key"].includes(tab);
|
||||
};
|
||||
|
||||
// 分类类型
|
||||
@@ -488,10 +489,10 @@ export const ProviderPoolPage = forwardRef<ProviderPoolPageRef>(
|
||||
})}
|
||||
{/* Gemini API Key - 配置文件存储但归类到 API Key */}
|
||||
<button
|
||||
onClick={() => setActiveTab("gemini_api")}
|
||||
onClick={() => setActiveTab("gemini_api_key")}
|
||||
title="Gemini API Key"
|
||||
className={`group relative flex items-center gap-2 px-3 py-2 rounded-lg border transition-all ${
|
||||
activeTab === "gemini_api"
|
||||
activeTab === "gemini_api_key"
|
||||
? "border-primary bg-primary/10 text-primary shadow-sm"
|
||||
: "border-border bg-card hover:border-primary/50 hover:bg-muted text-muted-foreground hover:text-foreground"
|
||||
}`}
|
||||
@@ -501,7 +502,7 @@ export const ProviderPoolPage = forwardRef<ProviderPoolPageRef>(
|
||||
{(config?.credential_pool?.gemini_api_keys?.length ?? 0) > 0 && (
|
||||
<span
|
||||
className={`min-w-[1.25rem] h-5 flex items-center justify-center rounded-full text-xs font-medium ${
|
||||
activeTab === "gemini_api"
|
||||
activeTab === "gemini_api_key"
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "bg-muted-foreground/20 text-muted-foreground group-hover:bg-primary/20 group-hover:text-primary"
|
||||
}`}
|
||||
@@ -541,7 +542,7 @@ export const ProviderPoolPage = forwardRef<ProviderPoolPageRef>(
|
||||
</div>
|
||||
) : config ? (
|
||||
<div className="space-y-4">
|
||||
{activeTab === "gemini_api" && (
|
||||
{activeTab === "gemini_api_key" && (
|
||||
<>
|
||||
<GeminiApiKeySection
|
||||
entries={config.credential_pool?.gemini_api_keys ?? []}
|
||||
|
||||
@@ -56,4 +56,5 @@ export const providerLabels: Record<PoolProviderType, string> = {
|
||||
codex: "Codex (OpenAI OAuth)",
|
||||
claude_oauth: "Claude OAuth",
|
||||
iflow: "iFlow",
|
||||
gemini_api_key: "Gemini API Key",
|
||||
};
|
||||
|
||||
@@ -10,7 +10,8 @@ export type PoolProviderType =
|
||||
| "claude"
|
||||
| "codex"
|
||||
| "claude_oauth"
|
||||
| "iflow";
|
||||
| "iflow"
|
||||
| "gemini_api_key";
|
||||
|
||||
// Credential data types
|
||||
export interface KiroOAuthCredential {
|
||||
@@ -47,6 +48,13 @@ export interface ClaudeKeyCredential {
|
||||
base_url?: string;
|
||||
}
|
||||
|
||||
export interface GeminiApiKeyCredential {
|
||||
type: "gemini_api_key";
|
||||
api_key: string;
|
||||
base_url?: string;
|
||||
excluded_models?: string[];
|
||||
}
|
||||
|
||||
export interface CodexOAuthCredential {
|
||||
type: "codex_oauth";
|
||||
creds_file_path: string;
|
||||
@@ -74,6 +82,7 @@ export type CredentialData =
|
||||
| AntigravityOAuthCredential
|
||||
| OpenAIKeyCredential
|
||||
| ClaudeKeyCredential
|
||||
| GeminiApiKeyCredential
|
||||
| CodexOAuthCredential
|
||||
| ClaudeOAuthCredential
|
||||
| IFlowOAuthCredential
|
||||
@@ -327,6 +336,20 @@ export const providerPoolApi = {
|
||||
return invoke("add_claude_key_credential", { apiKey, baseUrl, name });
|
||||
},
|
||||
|
||||
async addGeminiApiKey(
|
||||
apiKey: string,
|
||||
baseUrl?: string,
|
||||
excludedModels?: string[],
|
||||
name?: string,
|
||||
): Promise<ProviderCredential> {
|
||||
return invoke("add_gemini_api_key_credential", {
|
||||
apiKey,
|
||||
baseUrl,
|
||||
excludedModels,
|
||||
name,
|
||||
});
|
||||
},
|
||||
|
||||
async addAntigravityOAuth(
|
||||
credsFilePath: string,
|
||||
projectId?: string,
|
||||
|
||||
Reference in New Issue
Block a user