Bug Description / Bug 描述
When configuring a Hermes provider (using DeepSeek API via OpenAI-compatible endpoint), the "配置用量查询" (Usage Query) script in the provider edit page returns 401 Unauthorized.
The API key itself is valid — a direct curl to https://api.deepseek.com/v1/user/balance with the same key returns 200 (balance data), and with an empty key returns 401. The bug is in how CC Switch reads credentials from settings_config.
Steps to Reproduce / 重现步骤
- Add a Hermes provider with DeepSeek API (e.g. base_url =
https://api.deepseek.com/v1, any API key)
- Go to the provider edit page
- Click the "配置用量查询" script test button
- See 401 Unauthorized error
Root Cause / 根因
In src-tauri/src/commands/provider.rs, the query_provider_usage_inner function, when template_type == TEMPLATE_TYPE_BALANCE, reads credentials from:
let env = settings_config.get("env");
let base_url = env.and_then(|e| e.get("ANTHROPIC_BASE_URL")).and_then(|v| v.as_str());
let api_key = env.and_then(|e| e.get("ANTHROPIC_AUTH_TOKEN")).and_then(|v| v.as_str());
However, for Hermes providers (and potentially other non-Claude providers), settings_config is stored as a flat object:
{
"api_key": "sk-xxx",
"base_url": "https://api.deepseek.com/v1",
"model": "deepseek-v4-flash"
}
There is no env sub-object, so both ANTHROPIC_AUTH_TOKEN and ANTHROPIC_BASE_URL resolve to None → empty credentials → 401 from the upstream API.
Proposed Fix / 修复方案
In provider.rs, the TEMPLATE_TYPE_BALANCE credential reading path should try the flat base_url/api_key fields first, then fall back to the env.ANTHROPIC_* fields for backward compatibility with Claude providers:
// Try flat fields first (Hermes, non-Claude providers), fall back to env.ANTHROPIC_*
let base_url = settings_config
.get("base_url")
.and_then(|v| v.as_str())
.or_else(|| env.and_then(|e| e.get("ANTHROPIC_BASE_URL").and_then(|v| v.as_str())));
let api_key = settings_config
.get("api_key")
.and_then(|v| v.as_str())
.or_else(|| env.and_then(|e| e.get("ANTHROPIC_AUTH_TOKEN").and_then(|v| v.as_str())));
Temporary Workaround / 临时解决方法
If you cannot recompile CC Switch, you can manually edit the SQLite database at ~/.cc-switch/cc-switch.db:
UPDATE providers SET settings_config = json_set(
settings_config,
$.env.ANTHROPIC_AUTH_TOKEN,
$.api_key,
$.env.ANTHROPIC_BASE_URL,
$.base_url
)
WHERE id = <provider_id>;
Then restart CC Switch. Note: re-editing the provider in the UI may overwrite settings_config and drop the env field, requiring a repeat of this workaround.
Environment / 环境
- CC Switch Version: (latest, date: 2026-05-20)
- OS: Windows
- Related App: Other / 其他 (Hermes agent via custom provider)
Bug Description / Bug 描述
When configuring a Hermes provider (using DeepSeek API via OpenAI-compatible endpoint), the "配置用量查询" (Usage Query) script in the provider edit page returns 401 Unauthorized.
The API key itself is valid — a direct
curltohttps://api.deepseek.com/v1/user/balancewith the same key returns 200 (balance data), and with an empty key returns 401. The bug is in how CC Switch reads credentials fromsettings_config.Steps to Reproduce / 重现步骤
https://api.deepseek.com/v1, any API key)Root Cause / 根因
In
src-tauri/src/commands/provider.rs, thequery_provider_usage_innerfunction, whentemplate_type == TEMPLATE_TYPE_BALANCE, reads credentials from:However, for Hermes providers (and potentially other non-Claude providers),
settings_configis stored as a flat object:{ "api_key": "sk-xxx", "base_url": "https://api.deepseek.com/v1", "model": "deepseek-v4-flash" }There is no
envsub-object, so bothANTHROPIC_AUTH_TOKENandANTHROPIC_BASE_URLresolve toNone→ empty credentials → 401 from the upstream API.Proposed Fix / 修复方案
In
provider.rs, theTEMPLATE_TYPE_BALANCEcredential reading path should try the flatbase_url/api_keyfields first, then fall back to theenv.ANTHROPIC_*fields for backward compatibility with Claude providers:Temporary Workaround / 临时解决方法
If you cannot recompile CC Switch, you can manually edit the SQLite database at
~/.cc-switch/cc-switch.db:Then restart CC Switch. Note: re-editing the provider in the UI may overwrite
settings_configand drop theenvfield, requiring a repeat of this workaround.Environment / 环境