chore: bump version to 0.17.7

This commit is contained in:
coso
2025-12-24 23:41:23 +08:00
parent e652f072d0
commit 9ca4dead61
9 changed files with 154 additions and 13 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "proxycast",
"private": true,
"version": "0.17.6",
"version": "0.17.7",
"type": "module",
"repository": {
"type": "git",
+1 -1
View File
@@ -3377,7 +3377,7 @@ dependencies = [
[[package]]
name = "proxycast"
version = "0.17.6"
version = "0.17.7"
dependencies = [
"anyhow",
"async-stream",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "proxycast"
version = "0.17.6"
version = "0.17.7"
description = "AI API Proxy Desktop App"
authors = ["you"]
edition = "2021"
+2 -1
View File
@@ -493,6 +493,7 @@ pub fn update_provider_pool_credential(
request.check_health,
request.check_model_name,
request.not_supported_models,
request.new_proxy_url,
)?
};
@@ -548,7 +549,7 @@ pub fn toggle_provider_pool_credential(
) -> Result<ProviderCredential, String> {
pool_service
.0
.update_credential(&db, &uuid, None, Some(is_disabled), None, None, None)
.update_credential(&db, &uuid, None, Some(is_disabled), None, None, None, None)
}
/// 重置凭证计数器
+11 -7
View File
@@ -18,7 +18,7 @@ impl ProviderPoolDao {
"SELECT uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count, error_count,
last_used, last_error_time, last_error_message, last_health_check_time,
last_health_check_model, created_at, updated_at, source
last_health_check_model, created_at, updated_at, source, proxy_url
FROM provider_pool_credentials
ORDER BY provider_type, created_at ASC",
)?;
@@ -41,7 +41,7 @@ impl ProviderPoolDao {
"SELECT uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count, error_count,
last_used, last_error_time, last_error_message, last_health_check_time,
last_health_check_model, created_at, updated_at, source
last_health_check_model, created_at, updated_at, source, proxy_url
FROM provider_pool_credentials
WHERE provider_type = ?1
ORDER BY created_at ASC",
@@ -67,7 +67,7 @@ impl ProviderPoolDao {
"SELECT uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count, error_count,
last_used, last_error_time, last_error_message, last_health_check_time,
last_health_check_model, created_at, updated_at, source
last_health_check_model, created_at, updated_at, source, proxy_url
FROM provider_pool_credentials
WHERE uuid = ?1",
)?;
@@ -89,7 +89,7 @@ impl ProviderPoolDao {
"SELECT uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count, error_count,
last_used, last_error_time, last_error_message, last_health_check_time,
last_health_check_model, created_at, updated_at, source
last_health_check_model, created_at, updated_at, source, proxy_url
FROM provider_pool_credentials
WHERE name = ?1",
)?;
@@ -131,8 +131,8 @@ impl ProviderPoolDao {
(uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count, error_count,
last_used, last_error_time, last_error_message, last_health_check_time,
last_health_check_model, created_at, updated_at, source)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19)",
last_health_check_model, created_at, updated_at, source, proxy_url)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20)",
params![
cred.uuid,
cred.provider_type.to_string(),
@@ -153,6 +153,7 @@ impl ProviderPoolDao {
cred.created_at.timestamp(),
cred.updated_at.timestamp(),
source_str,
cred.proxy_url,
],
)?;
Ok(())
@@ -171,7 +172,7 @@ impl ProviderPoolDao {
is_disabled = ?6, check_health = ?7, check_model_name = ?8,
not_supported_models = ?9, usage_count = ?10, error_count = ?11,
last_used = ?12, last_error_time = ?13, last_error_message = ?14,
last_health_check_time = ?15, last_health_check_model = ?16, updated_at = ?17
last_health_check_time = ?15, last_health_check_model = ?16, updated_at = ?17, proxy_url = ?18
WHERE uuid = ?1",
params![
cred.uuid,
@@ -191,6 +192,7 @@ impl ProviderPoolDao {
cred.last_health_check_time.map(|t| t.timestamp()),
cred.last_health_check_model,
cred.updated_at.timestamp(),
cred.proxy_url,
],
)?;
Ok(())
@@ -305,6 +307,7 @@ impl ProviderPoolDao {
let created_at_ts: i64 = row.get(16)?;
let updated_at_ts: i64 = row.get(17)?;
let source_str: Option<String> = row.get(18).ok();
let proxy_url: Option<String> = row.get(19).ok();
let provider_type: PoolProviderType =
provider_type_str.parse().unwrap_or(PoolProviderType::Kiro);
@@ -351,6 +354,7 @@ impl ProviderPoolDao {
.unwrap_or_default(),
cached_token: None, // 从 get_token_cache 单独获取
source,
proxy_url,
})
}
+117
View File
@@ -157,5 +157,122 @@ pub fn create_tables(conn: &Connection) -> Result<(), rusqlite::Error> {
[],
);
// Migration: 添加代理URL字段 - 使用重建表结构的方式
migrate_add_proxy_url_column(conn)?;
Ok(())
}
/// 迁移:添加proxy_url列到provider_pool_credentials表
/// 使用重建表结构的方式确保数据完整性
fn migrate_add_proxy_url_column(conn: &Connection) -> Result<(), rusqlite::Error> {
// 检查是否已经存在proxy_url列
let mut stmt = conn.prepare("PRAGMA table_info(provider_pool_credentials)")?;
let column_info: Vec<String> = stmt
.query_map([], |row| {
let column_name: String = row.get(1)?;
Ok(column_name)
})?
.collect::<Result<Vec<_>, _>>()?;
// 如果proxy_url列已存在,跳过迁移
if column_info.contains(&"proxy_url".to_string()) {
return Ok(());
}
tracing::info!("开始迁移:添加proxy_url列到provider_pool_credentials表");
// 开始事务
conn.execute("BEGIN TRANSACTION", [])?;
let migration_result = (|| -> Result<(), rusqlite::Error> {
// 1. 备份现有数据
conn.execute(
"CREATE TABLE provider_pool_credentials_backup AS
SELECT * FROM provider_pool_credentials",
[],
)?;
// 2. 删除原表
conn.execute("DROP TABLE provider_pool_credentials", [])?;
// 3. 重建表结构(包含proxy_url列)
conn.execute(
"CREATE TABLE provider_pool_credentials (
uuid TEXT PRIMARY KEY,
provider_type TEXT NOT NULL,
credential_data TEXT NOT NULL,
name TEXT,
is_healthy INTEGER DEFAULT 1,
is_disabled INTEGER DEFAULT 0,
check_health INTEGER DEFAULT 1,
check_model_name TEXT,
not_supported_models TEXT,
usage_count INTEGER DEFAULT 0,
error_count INTEGER DEFAULT 0,
last_used INTEGER,
last_error_time INTEGER,
last_error_message TEXT,
last_health_check_time INTEGER,
last_health_check_model TEXT,
proxy_url TEXT,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
cached_access_token TEXT,
cached_refresh_token TEXT,
token_expiry_time TEXT,
last_refresh_time TEXT,
refresh_error_count INTEGER DEFAULT 0,
last_refresh_error TEXT,
source TEXT DEFAULT 'manual'
)",
[],
)?;
// 4. 恢复数据(proxy_url默认为NULL)
conn.execute(
"INSERT INTO provider_pool_credentials (
uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count,
error_count, last_used, last_error_time, last_error_message,
last_health_check_time, last_health_check_model, proxy_url,
created_at, updated_at, cached_access_token, cached_refresh_token,
token_expiry_time, last_refresh_time, refresh_error_count,
last_refresh_error, source
) SELECT
uuid, provider_type, credential_data, name, is_healthy, is_disabled,
check_health, check_model_name, not_supported_models, usage_count,
error_count, last_used, last_error_time, last_error_message,
last_health_check_time, last_health_check_model, NULL as proxy_url,
created_at, updated_at, cached_access_token, cached_refresh_token,
token_expiry_time, last_refresh_time, refresh_error_count,
last_refresh_error, source
FROM provider_pool_credentials_backup",
[],
)?;
// 5. 重建索引
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_provider_pool_type ON provider_pool_credentials(provider_type)",
[],
)?;
// 6. 删除备份表
conn.execute("DROP TABLE provider_pool_credentials_backup", [])?;
Ok(())
})();
match migration_result {
Ok(()) => {
conn.execute("COMMIT", [])?;
tracing::info!("proxy_url列迁移成功完成");
Ok(())
}
Err(e) => {
conn.execute("ROLLBACK", [])?;
tracing::error!("proxy_url列迁移失败,已回滚: {}", e);
Err(e)
}
}
}
+15 -1
View File
@@ -228,6 +228,8 @@ pub struct ProviderCredential {
/// 凭证来源(手动添加/导入/私有)
#[serde(default)]
pub source: CredentialSource,
/// 代理 URL(可覆盖全局代理设置)
pub proxy_url: Option<String>,
}
fn default_true() -> bool {
@@ -259,6 +261,7 @@ impl ProviderCredential {
updated_at: now,
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
}
}
@@ -526,6 +529,8 @@ pub struct CredentialDisplay {
pub base_url: Option<String>,
/// API Key 凭证的完整 api_key(仅用于 OpenAI/Claude API Key 类型,用于编辑)
pub api_key: Option<String>,
/// 凭证级代理 URL(可覆盖全局代理设置)
pub proxy_url: Option<String>,
}
/// 获取凭证类型字符串
@@ -623,6 +628,7 @@ impl From<&ProviderCredential> for CredentialDisplay {
source: cred.source,
base_url: get_base_url(&cred.credential),
api_key: get_api_key(&cred.credential),
proxy_url: cred.proxy_url.clone(),
}
}
}
@@ -664,7 +670,7 @@ pub struct AddCredentialRequest {
pub check_model_name: Option<String>,
}
/// 更新凭证的请求结构
/// 更新凭证请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateCredentialRequest {
pub name: Option<String>,
@@ -680,6 +686,8 @@ pub struct UpdateCredentialRequest {
pub new_base_url: Option<String>,
/// API Key 相关:新的 api_key(仅适用于 API Key 凭证)
pub new_api_key: Option<String>,
/// 新的代理 URL(可覆盖全局代理设置)
pub new_proxy_url: Option<String>,
}
pub type ProviderPools = HashMap<PoolProviderType, Vec<ProviderCredential>>;
@@ -747,6 +755,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
assert!(!cred.supports_model("claude-opus"));
@@ -780,6 +789,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
// Exact match exclusion
@@ -815,6 +825,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
// Prefix wildcard exclusion
@@ -854,6 +865,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
// Contains wildcard exclusion
@@ -890,6 +902,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
// Excluded by not_supported_models (exact match)
@@ -927,6 +940,7 @@ mod tests {
updated_at: Utc::now(),
cached_token: None,
source: CredentialSource::Manual,
proxy_url: None,
};
// All models should be supported since not_supported_models is empty
@@ -131,6 +131,7 @@ impl ProviderPoolService {
check_health: Option<bool>,
check_model_name: Option<String>,
not_supported_models: Option<Vec<String>>,
proxy_url: Option<String>,
) -> Result<ProviderCredential, String> {
let conn = db.lock().map_err(|e| e.to_string())?;
let mut cred = ProviderPoolDao::get_by_uuid(&conn, uuid)
@@ -154,6 +155,10 @@ impl ProviderPoolService {
if let Some(models) = not_supported_models {
cred.not_supported_models = models;
}
// 处理 proxy_url:空字符串表示清除,None 表示不修改
if let Some(p) = proxy_url {
cred.proxy_url = if p.is_empty() { None } else { Some(p) };
}
cred.updated_at = Utc::now();
ProviderPoolDao::update(&conn, &cred).map_err(|e| e.to_string())?;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "ProxyCast",
"version": "0.17.6",
"version": "0.17.7",
"identifier": "com.proxycast.app",
"build": {
"beforeDevCommand": "npm run dev",