fix(config): 保存不再误删 CLI 后加的顶层配置节 + 未知供应商类型原样保留
- 导出 stale-key 清理增加导入基线(imported_section_keys):CLI 在导入后 新增的顶层节(kimi-code 0.38+ 的 [task]/[swarm]/[cron] 等)在保存时 原样保留;用户在 UI 显式删除的节仍被移除;空基线(SQLite 快照恢复) 不删任何键(安全退化) - ProviderType 增加 Unknown(String) 变体,手写 serde 保持纯字符串线格式, 上游新增的 type 值往返不再被改写为 kimi;SQLite 快照恢复路径同步修复; 模型发现对未知类型返回明确错误,不再误用 KIMI_API_KEY - 新增 3 个往返测试(106 个 Rust 测试全绿),前端 tsc/vitest 通过
This commit is contained in:
1 parent
9764929919
commit
67db19eda4
9 files changed
+251
-58
No files matched your search
+21
-11
@@ -244,6 +244,7 @@ fn build_active_config(config: &Config) -> Config {
|
||||
providers,
|
||||
models,
|
||||
raw_other: config.raw_other.clone(),
|
||||
imported_section_keys: config.imported_section_keys.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +278,9 @@ pub async fn list_provider_models(provider: Provider) -> Result<Vec<DiscoveredMo
|
||||
ProviderType::Anthropic => fetch_anthropic_models(&base, &api_key).await,
|
||||
ProviderType::GoogleGenai => fetch_google_genai_models(&base, &api_key).await,
|
||||
ProviderType::Vertexai => Err("Vertex AI model discovery requires GCP project/location configuration and is not yet supported".to_string()),
|
||||
ProviderType::Unknown(s) => Err(format!(
|
||||
"unsupported provider type for model discovery: {s}"
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,8 +342,12 @@ fn resolve_api_key(provider: &Provider) -> Option<String> {
|
||||
return Some(key.clone());
|
||||
}
|
||||
}
|
||||
let env_key = expected_api_key_key(&provider.provider_type);
|
||||
provider.env.get(env_key).filter(|s| !s.is_empty()).cloned()
|
||||
if let Some(env_key) = expected_api_key_key(&provider.provider_type) {
|
||||
if let Some(key) = provider.env.get(env_key).filter(|s| !s.is_empty()) {
|
||||
return Some(key.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn resolve_base_url(provider: &Provider) -> String {
|
||||
@@ -356,13 +364,16 @@ fn resolve_base_url(provider: &Provider) -> String {
|
||||
})
|
||||
}
|
||||
|
||||
fn expected_api_key_key(provider_type: &ProviderType) -> &'static str {
|
||||
/// Well-known env var fallback for the API key per provider type; `None`
|
||||
/// for unknown types (no well-known variable name to look up).
|
||||
fn expected_api_key_key(provider_type: &ProviderType) -> Option<&'static str> {
|
||||
match provider_type {
|
||||
ProviderType::Kimi => "KIMI_API_KEY",
|
||||
ProviderType::Anthropic => "ANTHROPIC_API_KEY",
|
||||
ProviderType::Openai | ProviderType::OpenaiResponses => "OPENAI_API_KEY",
|
||||
ProviderType::GoogleGenai => "GOOGLE_API_KEY",
|
||||
ProviderType::Vertexai => "VERTEXAI_API_KEY",
|
||||
ProviderType::Kimi => Some("KIMI_API_KEY"),
|
||||
ProviderType::Anthropic => Some("ANTHROPIC_API_KEY"),
|
||||
ProviderType::Openai | ProviderType::OpenaiResponses => Some("OPENAI_API_KEY"),
|
||||
ProviderType::GoogleGenai => Some("GOOGLE_API_KEY"),
|
||||
ProviderType::Vertexai => Some("VERTEXAI_API_KEY"),
|
||||
ProviderType::Unknown(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,9 +661,8 @@ pub async fn query_provider_usage(
|
||||
.clone()
|
||||
.filter(|s| !s.trim().is_empty())
|
||||
.or_else(|| {
|
||||
provider
|
||||
.env
|
||||
.get(expected_api_key_key(&provider.provider_type))
|
||||
expected_api_key_key(&provider.provider_type)
|
||||
.and_then(|env_key| provider.env.get(env_key))
|
||||
.cloned()
|
||||
.filter(|s| !s.is_empty())
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user