不猜是一种功能:CC Switch 的自定义配置取舍
在一个管配置的工具里新建自定义供应商,填完请求地址,敲进一个模型 ID。工具认识这串字符吗?它该不该顺手替你把「支持扩展思考」勾上、把上下文长度填成一个看起来对的数?
CC Switch 在管理 Pi 这条路径上,把这两个问题的答案写进了需求文档的第 4 行,当成一条产品原则来执行。答案是:不猜。
这篇拆的就是这条原则:它具体禁止了什么,逼出了哪些界面规则,代价落在谁身上。
先说清这篇文章的依据
本文只做一件事——静态读源码和文档。所依据的是 farion1231/cc-switch 仓库的 v3.20.1 快照(commit 3217f725),核对日 2026-08-31。我们没有编译过它,没有安装过这个桌面应用,也没有跑过任何一次供应商切换。因此下文出现的「界面不显示 X」一律是规范文档写下的要求,不是我们看到的画面;出现的字段名与默认值一律来自源码行,不是使用观察。
一、原则出自哪一行
docs/pi-thinking-level-map-requirements-zh.md 的第 3–4 行是两句话:状态写「已实现并完成验收」,原则写「预设完整可靠,自定义配置不猜测;运行时不依赖外部模型目录」。
第 13 行把「不依赖」说死:当前版本不建设面向自定义供应商的运行时模型数据库,也不从上游客户端或任何第三方模型目录服务下载数据;外部资料只用于开发时人工核对预设。
由此分出两条互不混用的路径(第 9–11 行):
- 预设路径:由 CC Switch 自己维护完整的模型配置,选中即可直接保存。
- 自定义路径:自定义供应商与「获取模型列表」只帮忙填写模型 ID,不自动推断模型能力。
同一个软件里两套待遇,分界线不是模型有多常见,而是这份配置从哪来。
二、「完整可靠」那一侧的账单
既然运行时不查外部目录,预设就必须把能力离线携带全。文档第 24–32 行给了字段结构,它与 src/config/piModelCatalog.ts:5-11 的 PiModelCapabilities 接口逐个对得上:name、reasoning、input、contextWindow、maxTokens,模型 id 作为对象的键存在。
五条预设规则里最锋利的是这一条:预设别名只在该预设中有效,不能让自定义供应商中的同名 ID 自动获得能力。 同一串模型 ID,写在预设里带全套能力,用户自己敲进自定义供应商就什么都不带。字符串完全一样,来源不一样,待遇就不一样——这是整条原则最直白的一次表达。
配套的两条约束把口子彻底封住:预设数据必须随应用发布、离线可用;不从其他应用的预设或 Pi 运行时模型列表动态生成 Pi 预设。
账单也就清楚了:预设的正确性由项目自己扛,靠开发期人工核对,且预设的更新要跟着应用版本走。这是「不猜」换来的成本,不是白得的干净。
三、四种取值编码四种语义
真正把这条原则做到类型层面的,是 thinkingLevelMap 这个字段。
Pi 的思考档位是一个有限枚举 PiThinkingLevel,v3.20.1 的取值从 off 一路排到 max,中间是几档强度递增的名字——具体档名与档数属于会随版本变的东西,看当版文档为准。映射本身的类型是 Partial<Record<PiThinkingLevel, string | null>>。
关键在第 62–67 行,四种取值必须保留四种不同语义:
| 取值形态 | 含义 |
|---|---|
| 字符串 | 发送给上游的实际值 |
null | 该档位明确不可用 |
| 缺少某个键 | 该档位使用 Pi 的默认行为 |
{} | 整组明确使用 Pi 默认行为 |
紧接着两条禁令:稀疏映射不得被自动补齐;reasoning: true 不代表所有档位都可用。
后一条值得单独看。reasoning 是个布尔字段,它只告诉你这个模型会思考,不告诉你哪几档能用。把前者外推成后者,是一个极其自然的推断:既然模型会思考,档位当然都该能用。这份文档明写不许做这一步。这就是「不猜」在类型语义上的落点:能力的粒度是多少,就只能承诺多少。
预设侧还有一条配套要求(第 69–73 行):所有支持思考的预设模型都必须显式带 thinkingLevelMap;尚无可靠映射的写 {},明确交给原生行为。注意这里 {} 不是「还没写」,是一次明确的表态,跟「缺键」在语义上是两回事。另外,需要额外原生兼容字段的预设应同时写入必要的 compat,不能只让界面把档位显示出来了事。
四、原则怎么逼出界面规则
pi-thinking-level-map-requirements-zh.md:89 与 pi-frontend-uiux-guidelines-zh.md:149 给了同一条结论:界面不显示「自动值」「已覆盖自动值」「恢复自动值」,理由只有一句——自定义模型不存在后台推断值。
这三个词是「有推断值」这个前提的产物。前提没了,它们就没有指称对象,摆上去只会让用户以为背后有一套他看不见的默认逻辑。
前端规范同一行还把「猜」的常见路径逐条点名封死:后台不得根据已知名称、模型前缀、相似版本、URL 或外部目录自动写入能力。
于是自定义模型的表单规则(pi-thinking-level-map-requirements-zh.md:82-87)变成这样:
reasoning、input、contextWindow、maxTokens、thinkingLevelMap都不从本地目录或网络自动填写;- 上下文长度和最大输出 Token 必须填写正数后才能保存;
- 「支持扩展思考」与「支持图片输入」由用户明确选择,默认分别是关闭与仅文本;
- 开启扩展思考后才显示思考档位编辑器。
档位编辑器的排布也被规范写死了:排在上下文长度与最大输出之后作为最后一项,默认折叠;展开后用一份按档位逐行的轻量列表,直接呈现「字符串 / Pi 默认 / 不可用」三种状态,点击某一行才打开该档位的编辑浮层。最后一句是我觉得最见功力的:关闭「支持扩展思考」时整段隐藏,但不删除已有映射。
隐藏不删,同样是不猜——用户关掉一个开关,不代表他决定作废那份已经写好的映射。
五、同一条原则在别处的形状
翻遍这几份规格文档会发现,「不猜」不是某一个字段的局部处理,而是反复出现的同一种手法。
不猜默认选择。 pi-frontend-uiux-guidelines-zh.md:70-80 整节叫「Pi 当前选择的安全边界」:CC Switch 不设置、不展示、不标记 Pi 的当前供应商与模型,当前选择完全交给 Pi 原生的 /model;移除或删除供应商不得修改 defaultProvider 或 defaultModel;并且明写不得用「列表第一个模型」推导默认模型,也不得在保存供应商时偷偷修改默认选择。
不猜项目上下文。 项目级 .pi/settings.json 依赖启动 Pi 时的工作目录,而供应商页没有权威的项目上下文,于是它不扫描目录、不猜测活动会话(pi-frontend-uiux-guidelines-zh.md:80)。原生契约文档 pi-native-contract-zh.md:47-49 是同一个逻辑的另一半:会话枚举只处理绝对路径、~ 路径或默认目录,相对 sessionDir 明确显示「需要项目上下文」,而不是挑一个目录试试看。
不猜缺失字段的意图。 pi-frontend-uiux-guidelines-zh.md:167-173:原配置缺少可选字段时,用户没主动修改就应保持缺失;界面可以显示默认协议帮助理解,但保存不能自动补写这个字段。理解归理解,落盘归落盘。
不猜补写的时机。 pi-thinking-level-map-requirements-zh.md:93-98:旧模型缺少本版本要求的字段时,只在编辑表单里提示用户补全,用户保存后才落盘;应用启动、供应商列表刷新和外部配置同步不得静默补写模型能力。写入必须由一次明确的用户动作触发,不能搭着一次刷新溜进去。
不猜归属。 这条最有意思,因为它是判据本身被纠正过一次。pi-live-provider-sync-requirements-zh.md:5-7 记的原始 bug 是:当时按供应商 ID 与认证类型来判断「这份配置归不归我管」,结果 Pi 已经加载了的显式配置,在页面上却没有对应卡片,也没法移除、编辑或重新启用。修复原则写得很硬:是否属于可管理范围,应只由配置来源决定,不能再由供应商 ID 或认证类型决定。 修完之后连痕迹都清了——PI_BUILTIN_PROVIDER_KEYS 这个常量在 v3.20.1 的 src/ 与 src-tauri/src/ 里全库 grep 已是 0 命中。
六、这条原则的三个边界
边界一:这些是规范,不是运行结果。 前端规范自己第 36 行就写着「源码阅读和经验判断只能用于提出假设,不能作为产品状态的依据」。这句话对我们这种只读仓库的人同样成立:上面每一条都是文档要求与源码定义,不是对实际行为的保证。
边界二:规范里出现的名字不一定还活着。 同一份前端规范要求 Pi 前端不显示 gatewayStatus、不从预设写入 allowGateway 一类能力字段;而在 v3.20.1 里对这两个标识符(连同蛇形写法)做全库 grep,src/ 与 src-tauri/src/ 命中数为 0。规范的更新节奏与代码不同步,里面可能保留着已被移除或从未落地的命名。引用规范里的字段名之前,先去代码里搜一次。
边界三:不猜不等于不出错。 既然运行时不查外部目录,预设里的能力值就只有开发期人工核对这一道关——文档写明外部资料只用于开发时人工核对预设,也没有给出任何运行时的校正或兜底机制。一条填错的 contextWindow 后来靠什么被发现,这几份规格文档没有写。「完整可靠」的可靠性,押在发布前那次核对上。
七、想自己核一遍
不用装应用,克隆仓库后翻这几处就够了:docs/pi-thinking-level-map-requirements-zh.md(原则、字段结构、四种取值语义、自定义表单规则)、docs/pi-frontend-uiux-guidelines-zh.md(界面取舍与当前选择边界)、docs/pi-native-contract-zh.md(读写边界与「明确不做」清单)、docs/pi-live-provider-sync-requirements-zh.md(判据纠错的来龙去脉),代码侧对照 src/config/piModelCatalog.ts 与 src/config/piProviderPresets.ts。
顺带说一句:这四份文档不是用户手册,是给开发者与评审者看的准入规则。把它们当手册读会失望,当设计取舍的说明书读收获会大得多——一个工具敢把「我不替你猜」写进需求并给出理由,比它多支持几个字段更值得看。
本文依据 CC Switch 官方仓库(github.com/farion1231/cc-switch)的 README、docs/ 下的用户手册、
路由指南与发布说明,以及 src/、src-tauri/、tests/ 的源码整理,
核对日 2026-08-31,对应仓库快照 3217f725(仓库内版本号 3.20.1)。
本文内容为仓库源码与文档口径,我们没有安装或运行过这个桌面应用,
因此不涉及界面外观、操作手感与切换速度的任何描述。
文中出现的阈值与默认值均为源码中的默认配置,不构成对实际运行结果的保证。
该项目仍在快速迭代,版本与默认值随时可能变动,请以仓库最新内容为准。
安全相关做法请结合自身环境评估,本文不构成安全方案建议。
留言讨论
评论发布后会被人工复核,违规内容将被删除。
如果发表没有反应,可以前往联系我们告诉我们。