一条预设长什么样:`ProviderPreset` 的字段全集与各自作用
打开 src/config/claudeProviderPresets.ts 的头部,ProviderPreset 这个接口一口气定义了 21 个字段(src/config/claudeProviderPresets.ts:25-74)。看接口的时候很容易产生一个印象:一条预设大概就是这 21 个字段填满的样子。
把下面 72 条预设逐个字段数一遍,得到的却是另一幅图景:出现次数满格(72/72)的只有 4 个字段,一半的字段(10 个)只出现在个位数条目上,另有 1 个字段一次都没被用过。
这篇就把这张字段表摊开:每个字段在哪一层、实际被用了多少次、改动它会牵动什么。以下全部基于我们本地 clone 的 cc-switch 仓库快照 c39c903(提交日期 2026-08-10),仓库内版本号 3.19.2,只读源码文本,没有安装也没有运行过这个桌面应用。
21 个字段与它们的实际出现次数
先看表。出现次数一列的口径是:Claude Code 那个 providerPresets 数组的 72 条条目里,该字段作为一级字段出现了多少次。
| 字段 | 72 条中出现 | 这个字段管什么 |
|---|---|---|
name | 72 | 预设名 |
websiteUrl | 72 | 供应商站点地址 |
settingsConfig | 72 | 要写进 live 配置的那份内容(Claude 侧对应 settings.json) |
category | 72 | 分类 |
icon | 69 | 图标名称 |
apiKeyUrl | 59 | 单独获取 API Key 的链接 |
iconColor | 45 | 图标颜色 |
partnerPromotionKey | 39 | 合作伙伴促销信息的 i18n key |
isPartner | 36 | 商业合作伙伴标识 |
endpointCandidates | 27 | 请求地址候选列表,供地址管理与测速使用 |
apiFormat | 6 | API 格式,四取值 |
nameKey | 4 | 本地化显示名的 i18n key |
theme | 3 | 视觉主题配置 |
apiKeyField | 3 | 该预设使用的 API Key 字段名 |
templateValues | 3 | 模板变量定义 |
providerType | 3 | 供应商类型标识 |
requiresOAuth | 3 | 是否需要 OAuth 认证 |
primePartner | 2 | 置顶合作伙伴 |
isOfficial | 1 | 官方预设标识 |
modelsUrl | 1 | 获取模型列表使用的完整 URL |
hidden | 0 | 预设仍存在,但不在列表显示 |
这张表的读法不是「字段清单」,而是一条分层线。72、69、59、45 这几档是「大多数预设都会填」的部分;到 apiFormat 那一行断崖式掉到 6,往下全是个位数。也就是说,接口里那 21 个字段里,真正描述「一条预设普遍长什么样」的只有前面十行左右,后面十一行是为少数特殊条目开的口子。
满格的四个字段:一条预设的最小骨架
name、websiteUrl、settingsConfig、category 这四个在 72 条里一条不落。它们的分工其实是三件不同的事:
name 与 websiteUrl 是标识层,回答「这是谁」。注意 name 是写死的字符串,本地化显示名走的是另一个字段 nameKey,而 nameKey 在 72 条里只出现 4 次——绝大多数预设不做多语言显示名。顺带一提,nameKey 全仓一共只有 7 个不同取值,在多个预设文件中重复出现(各自出现 8/8/6/6/1/1/1 次)。
settingsConfig 是配置层,也是这条预设里体量最大的一块,决定选了它之后往 live 配置里写进什么内容。但它不是唯一影响运行的字段——apiFormat、providerType 参与路由是否接管的判定,apiKeyField 决定 Key 写在哪个字段名下(本文后面会分别说)。Claude 侧它对应 settings.json 的内容形态;同名字段在别的应用里形态并不一样,这一点下面还会说。
category 是分类层。Claude 的 72 条一条不落地都填了 category,而 Codex、Grok Build 那边有条目没填,可见它不是每条都必须有的字段。ProviderCategory 一共 8 个取值:official、cn_official、cloud_provider、aggregator、third_party、custom、omo、omo-slim(src/types.ts:1-9)。分类的分布情况、以及别的应用预设里各有几条漏填 category,我们另有一篇专门讲,这里不展开。
中间那一档:展示信息与地址候选
icon 69、apiKeyUrl 59、iconColor 45 这三个,属于「大部分填了、少数没填」。icon 与 iconColor 是展示用的元信息,跟请求怎么发没关系;apiKeyUrl 是「去哪儿拿 Key」的跳转地址,和 websiteUrl 是两个字段——有 13 条预设填了站点地址但没有单独的取 Key 地址。
isPartner 36、partnerPromotionKey 39、primePartner 2 这三个是合作伙伴标记位。primePartner 的注释写它是「置顶合作伙伴」,徽章显示为心形。这里只说结构:这三个字段的存在意味着预设列表里混着商业合作的标记,它们是数据模型的一部分。 具体哪些条目带这些标记、对应哪些服务商,我们按纪律没有采集,本文也不涉及任何服务商的名字、域名与相关文案。
endpointCandidates 27 条值得单独说一句。它是「请求地址候选列表」,供地址管理与测速使用——也就是说,同一个预设可以携带多个可选的接入地址。这个字段在 Claude 72 条里只有 27 条有,在 Codex 67 条里则有 59 条(src/config/codexProviderPresets.ts 一侧统计),两个应用的填写密度差得很远。相关的自定义端点还有一条落盘细节:add_custom_endpoint 会把 URL 先 trim、再去掉尾斜杠后才存,空字符串直接报错 provider.endpoint.url_required(src-tauri/src/services/provider/endpoints.rs:34-54);get_custom_endpoints 的返回结果按 added_at 倒序(:40-42)。
长尾那一档:为个位数条目开的特例
从 apiFormat 往下,全是个位数。这一档里最容易被误读的是 apiKeyField。
apiKeyField 只有两个取值:ANTHROPIC_AUTH_TOKEN(默认)与 ANTHROPIC_API_KEY(src/config/claudeProviderPresets.ts:36)。72 条里只有 3 条填了它。这不代表另外 69 条没有 Key 字段,而是它们走默认值。 后端那侧的语义是配套的:claude_uses_api_key_field() 的注释写明,表单只在「非默认选择」时才持久化 meta.apiKeyField,因此这个值为 None 就代表默认的 ANTHROPIC_AUTH_TOKEN(src-tauri/src/provider.rs:86-97)。前端预设的稀疏和后端元数据的稀疏是同一套约定——「字段不存在」在这里是一个有意义的取值,不是数据缺失。 你要判断某条预设用哪个 Key 字段名,不能只看这个字段在不在,得先知道缺省意味着什么。
apiFormat 6 条同理。四个取值是 anthropic(默认,直接透传)、openai_chat、openai_responses、gemini_native,后三者需要格式转换(src/config/claudeProviderPresets.ts:53-58)。72 条里只有 6 条填了,剩下 66 条都是默认的直接透传。这个字段还会参与路由是否接管的判定,判定链另有一篇在讲,这里只强调它在数据里的稀疏度。
providerType 与 requiresOAuth 各 3 条,恰好对应三条托管 OAuth 预设,分别在 src/config/claudeProviderPresets.ts:1241、:1271、:1291,三条都带 requiresOAuth: true。isOfficial 只有 1 条,就是官方那条,它的 settingsConfig 是 { env: {} },即空环境变量(src/config/claudeProviderPresets.ts:77-93)。modelsUrl 同样只有 1 条。
templateValues 3 条,它的值类型是另一个接口 TemplateValueConfig,字段是 label / placeholder / defaultValue? / editorValue(src/config/claudeProviderPresets.ts:6-11)。theme 3 条,类型 PresetTheme 三个字段:icon(取值 claude/codex/gemini/generic)、backgroundColor、textColor,颜色支持 Tailwind 类名或 hex(src/config/claudeProviderPresets.ts:16-23)。
最后是 hidden:接口里定义了(src/config/claudeProviderPresets.ts:69-70),语义是「预设仍存在,但不在列表显示」,而 grep -c 'hidden: true' src/config/*.ts 在八个预设文件里全部为 0。定义存在、零使用——这是可核实的事实,至于为什么,我们不做推断。
反直觉的那一处:ProviderPreset 不是唯一的预设接口
上面这张表只对 Claude Code 那个数组成立。真正容易踩的坑在这儿:八个应用的预设不是同一个接口,字段全集各不相同,同一件事在不同应用里放的位置也不同。
最典型的是 Claude Desktop。它的预设与 Claude Code 形态不同:baseUrl 是顶级字段,而不是 settingsConfig.env.ANTHROPIC_BASE_URL;模型信息以「Desktop 可见模型 ID → 上游模型」的形式表达;而且它有一个必填的 mode: "direct" | "proxy"(src/config/claudeDesktopProviderPresets.ts:1-9、:43-66)。也就是说,你在 Claude Code 预设里要往 settingsConfig 里钻两层才能找到的接入地址,在 Claude Desktop 预设里是平铺在顶层的。它的路由子结构 ClaudeDesktopRoutePreset 又是四个字段:routeId / upstreamModel / labelOverride / supports1m(:20-25)。
其余几个应用的独有字段:
| 应用 | 接口 | 相对 Claude 的独有字段 |
|---|---|---|
| Codex | CodexProviderPreset | auth(写入 ~/.codex/auth.json)、config(TOML 字符串,写入 ~/.codex/config.toml)、isCustomTemplate、modelCatalog、codexChatReasoning、promptCacheRouting |
| Gemini | GeminiProviderPreset | baseURL、model、description,主题是独立类型 GeminiPresetTheme |
| Hermes | HermesProviderPreset | suggestedDefaults(切换时写入 YAML 顶层 model: 段) |
| OpenClaw | — | suggestedDefaults 含 model 与 modelCatalog |
| Claude Desktop | ClaudeDesktopProviderPreset | baseUrl(顶级)、mode、modelRoutes |
Codex 那一行还有个细节:它的 providerType 只允许 "xai_oauth" 一个取值(src/config/codexProviderPresets.ts:13-46),比 Claude 侧的三取值窄;apiFormat 也是独立类型 CodexApiFormat,三个值:openai_responses(原生透传)/ openai_chat(需本地路由转换)/ anthropic。Gemini 的 GeminiPresetTheme 的 icon 只有 gemini 与 generic 两个取值(src/config/geminiProviderPresets.ts:6-33)。
所以「一条预设长什么样」这个问题没有单一答案。你要读预设,第一步不是打开接口,而是先确定你在看哪个应用的预设文件——settingsConfig 在 Claude 里是配置主体,在 Codex 里根本不是这个名字(是 auth + config 两个字段),在 Claude Desktop 里接入地址干脆不在 settingsConfig 里。
你自己怎么把这些数重新数一遍
字段出现次数不能靠肉眼,也不能直接 grep 字段名——预设文件里嵌套很深,settingsConfig、theme、templateValues 内部还有同名或形似的键。我们的做法分三步:
- 写一个花括号深度解析器:先剥掉
//与/* */注释和字符串字面量,再从export const <数组名> ... = [起扫描,只统计深度为 0 的{,即数组的顶层对象字面量;同一趟顺便统计每个条目的一级字段出现次数。 - 换一条独立路径交叉校验条目数:
grep -c '^ name: ' src/config/claudeProviderPresets.ts
四空格缩进的 name: 恰好只落在顶层条目上,两法结果一致才作数。
- 专项确认零使用字段:
grep -c 'hidden: true' src/config/*.ts
坑在第一步的「剥注释」上:不剥注释就会把注释行当成字段。 src/config/codexProviderPresets.ts:1440 有一行形如 // store:false / ... 的注释,未剥注释时会被解析器误判成一个 store 字段,字段统计随之虚高;剥掉注释后它消失。本文所有字段次数都取剥注释之后的口径,你要复现,这一步别省。
什么情况说明你数出来的和本文对不上不是方法问题? 两种:一是你的仓库快照不是 c39c903——预设条目是随版本变动的内容,条目数变了字段次数必然跟着变;二是你数的是别的应用的预设文件——本文这张 21 行的表只对 Claude Code 的 72 条成立,Codex、Gemini、Hermes 那几个数组的字段分布各是各的。这两条都排除之后仍然对不上,才值得回头检查解析口径。
这些字段该怎么改
坦白说,这个问题在这个仓库里没有通用答案,我们也不打算编一个。能确定的只有几条边界:
settingsConfig决定写进 live 配置的那份内容主体(live 的最终内容还会与通用配置片段合成),icon、iconColor、nameKey这类展示信息改了不改变请求本身怎么发。- 缺省有语义。
apiKeyField不填就是ANTHROPIC_AUTH_TOKEN,apiFormat不填就是anthropic直接透传。你把一个字段显式写成默认值,和不写它,在前端预设层面看起来等价,但后端meta那侧的持久化行为是按「只存非默认选择」设计的(src-tauri/src/provider.rs:86-97)。 endpointCandidates是给地址管理与测速用的候选池,往里加地址会作用在地址管理与测速这两处;它是否还牵动别的路径,我们手上的依据里没有记录,不下结论。- 至于每个字段该填什么值合适,取决于你接的是什么上游,项目没有给出通用值,本文也不给。
最后是一条安全提醒:CC Switch 处理的是本机上真实的 CLI 配置文件与 API Key。预设只是模板,你填进去的 Key 落在本机的配置与数据里,属于敏感数据,怎么保管请结合自身环境评估。
还有两条边界要说清楚:我们没有逐条阅读任何一条预设的具体内容(服务商名称、域名、模型 id、endpointCandidates 的取值都没采集),所以本文只有结构与计数,没有任何一家上游的信息;我们也没有运行过这个应用,字段与「实际用起来是什么效果」之间的关系不在本文的讨论范围内。
本文依据 CC Switch 官方仓库(github.com/farion1231/cc-switch)的 README、docs/ 下的用户手册与发布说明、
src/config/ 的预设定义与 src-tauri/src/ 的后端源码整理,核对日 2026-08-10,对应仓库快照 c39c903。
本文内容为仓库源码与文档口径,我们没有安装或运行过这个桌面应用,
因此不涉及界面外观、操作手感与切换速度的任何描述。
文中出现的阈值与默认值均为源码中的默认配置,不构成对实际运行结果的保证。
该项目仍在快速迭代,版本与默认值随时可能变动,请以仓库最新内容为准。
安全相关做法请结合自身环境评估,本文不构成安全方案建议。