fix(pi): resolve $NAME references in apiKey for usage queries

Pi lets a models.json provider's apiKey be "$NAME" / "${NAME}" (read from
the environment, with "$$" and "$!" as literal "$" and "!") or "!command".
CC Switch's own usage queries (Coding Plan, balance, usage-script
{{apiKey}}) read the Pi apiKey verbatim through resolve_usage_credentials,
so the provider received "Bearer $COMMAND_API_KEY" and answered 401.

Resolve the value with Pi's template rules before sending it. A referenced
variable that is unset or empty leaves the value unresolved, as in Pi, and
"!command" values are still never run by CC Switch; both now give an empty
key instead of sending the reference as the credential. The resolved key is
only used for the outgoing request and is never written back.

Refs #8822
This commit is contained in:
Jason committed 2026-10-24 22:56:15 +08:00
1 parent 442df1db70
commit dcdcbcb473
3 files changed
+107 -3

No files matched your search

+1 -1
View File
@@ -28,7 +28,7 @@
- 供应商级 `name`、`baseUrl`、`apiKey`、`api`、`headers`
- 模型级 `id`、`name`、`reasoning`、`input`、`contextWindow`、`maxTokens`
已有配置中的其他字段原样保留。供应商是否可管理只取决于节点是否显式存在于 `models.json.providers`:`anthropic`、`openai`、`deepseek` 等 Pi 内置 ID,以及带有未知字段的节点,都按普通显式配置同步。CC Switch 不把 Pi 运行时合并出的内置模型复制回配置,也不解析或执行 `apiKey`、Header 中的环境变量和命令表达式。请求仍由 Pi 自己发出。
已有配置中的其他字段原样保留。供应商是否可管理只取决于节点是否显式存在于 `models.json.providers`:`anthropic`、`openai`、`deepseek` 等 Pi 内置 ID,以及带有未知字段的节点,都按普通显式配置同步。CC Switch 不把 Pi 运行时合并出的内置模型复制回配置,也不执行 `apiKey`、Header 中的命令表达式。请求仍由 Pi 自己发出;只有 CC Switch 自己发的用量查询会按 Pi 的规则展开 `apiKey` 里的环境变量引用(`$NAME` / `${NAME}`),展开结果不写回配置,`!command` 和未设置的变量都按没有 Key 处理。
Pi 在全局设置中保存的当前供应商和模型不进入供应商列表状态。启用供应商只把条目加入 `models.json`,不会写 `defaultProvider` 或 `defaultModel`。移除或删除全局默认供应商时,前端在原有确认框内给出非阻塞提醒,后端允许继续且不改写默认项。编辑显式供应商同样不修改当前供应商或模型;失效引用和回退由 Pi 原生处理。