chore: bump version to 0.17.9

This commit is contained in:
coso
2025-12-25 00:12:10 +08:00
parent 4a64ae76c7
commit 35c5612d1f
11 changed files with 111 additions and 15 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "proxycast",
"private": true,
"version": "0.17.8",
"version": "0.17.9",
"type": "module",
"repository": {
"type": "git",
+1 -1
View File
@@ -3377,7 +3377,7 @@ dependencies = [
[[package]]
name = "proxycast"
version = "0.17.8"
version = "0.17.9"
dependencies = [
"anyhow",
"async-stream",
+1 -1
View File
@@ -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(
+1
View File
@@ -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 -1
View File
@@ -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",
};
+24 -1
View File
@@ -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,