CC-Switch 供应商体系与多协议兼容架构 (CC-Switch Provider Architecture & Multi-Protocol Compatibility)
1. 核心背景与架构动因 (Background and Motivation)
在大模型编码智能体(如 Claude Code、InPage Agent、Codex CLI 等)的落地场景中,开发者往往面临跨多云、多供应商切换的复杂现实。各大供应商在 API 协议上呈现明显割裂,主流分为三大协议族:
- Anthropic 原生 Messages API 协议 (
anthropic):以/v1/messages为核心,严格要求角色交替 (user与assistant),工具结果以tool_result块置于user角色中回传,使用anthropic-version、x-api-key与thinking预算。 - OpenAI 传统 Chat Completions 协议 (
openai_chat):以/v1/chat/completions为核心,具备独立的role: 'tool'角色与tool_calls结构,依赖data: [DONE]流式结尾。 - OpenAI 新一代 Responses API 协议 (
openai_responses):扁平化input序列,将system转为顶层instructions,工具调用提升为平级function_call与function_call_output项,采用细粒度命名事件生命周期(response.output_item.added、response.function_call_arguments.delta等)。
CC-Switch 作为目前最完备的桌面端大模型配置管理与中继切换工具,沉淀了一套高可用、泛化性极强的供应商体系与端点探测机制。本文档提炼其设计范式,用于为自主 Agent 提供企业级多协议兼容运行时。
2. 供应商 API Profile 字段规格 (Provider Profile Specification)
一个具备生产可用性的供应商单一 Profile 实体包含如下关键维度:
| 字段名 | 类型 | 说明与规范 | ||||
|---|---|---|---|---|---|---|
id | string | 运行时不可变唯一标识符 (UUID 或 nanoId) | ||||
name | string | 界面展示名称(如 "Claude Official"、"火山 Agent Plan") | ||||
baseUrl | string | 目标服务端点 Base URL(支持纯域名、/v1 或兼容子路径) | ||||
apiKey | string | 推理鉴权凭据 (API Key / Token) | ||||
apiFormat | `'anthropic' \ | 'openai_chat' \ | 'openai_responses'` | 协议类型,决定请求体序列化与 SSE 流式状态机解码方式 | ||
model | string | 当前激活/选中的默认模型名 | ||||
models | string[] | 该供应商预置或动态拉取到的候选模型下拉菜单列表 | ||||
customModels | string[] | 用户手动录入并持久化的自定义扩展模型名 | ||||
category | ProviderCategory | 分类:official (国际官方), cn_official (国内大厂), cloud_provider (云服务商), aggregator (聚合商) | ||||
websiteUrl | string | 供应商控制台/官方文档导航链接 | ||||
apiKeyUrl | string | 快捷获取 API Key 的直达网页地址 | ||||
icon / iconColor | string | 供应商品牌图标名及十六进制主题色 | ||||
customHeaders | Record<string, string> | 针对特殊网关额外注入的私有 HTTP 头 | ||||
reasoningEffort | `'none' \ | 'low' \ | 'medium' \ | 'high' \ | 'xhigh'` | 思考与推理强度档位 |
maxTokens | number | 单次生成最大 token 上限(Anthropic 强制要求必填) |
3. 预设供应商筛选逻辑 (Curated Presets Logic)
在桌面与前端 Agent 预设集成中,应遵循“保留第一梯队官方与大厂,剔除低信誉引流中转站”的原则:
保留清单
- 国际官方与开源旗舰:Anthropic (Claude Official), OpenAI Official, Google Gemini (Gemini Native), DeepSeek (深度求索), xAI (Grok), GitHub Copilot。
国内一线大厂专线:
- 月之暗面 (Moonshot):Kimi, Kimi For Coding。
- 字节跳动 (Volcengine):火山 Agent Plan, 火山 Coding Plan, 火山豆包 (DouBaoSeed), BytePlus。
- 阿里巴巴 (Alibaba Cloud):阿里百炼 (DashScope), 百炼 Coding Plan, 百炼 Token Plan, ModelScope (魔搭)。
- 智谱清言 (Zhipu BigModel):Zhipu GLM, 智谱 Coding Plan, Zhipu GLM en (Z.AI)。
- 百度千帆 (Baidu Qianfan):千帆 Coding Plan, 千帆 Token Plan。
- 腾讯混元 (Tencent Cloud):腾讯 Token Plan (LKEAP)。
- 其他头部独角兽:MiniMax (稀宇科技), 阶跃星辰 (StepFun), 小米 (Xiaomi MiMo), 美团 (Longcat)。
- 优质云计算与推理基础设施:硅基流动 (SiliconFlow), 七牛云 (Qiniu), 优云智算 (Compshare), OpenRouter, Nvidia (NIM), Novita AI。
过滤清单
- 彻底移除带推广标识或非官方中转分销站(如 PackyCode, ZetaAPI, APINebula, AICodeMirror, RunAPI, 胜算云, AIGoCode, AICoding, SubRouter, APIKEY.FUN, 9527CODE, Code0, PPIO, CCSub 等),防止接口生命周期不可靠及安全隐患。
4. 候选模型地址探测与后缀剥离机制 (Candidate URL Derivation)
多数支持 Anthropic 协议的供应商(如 DeepSeek、智谱、Kimi、火山)将 Anthropic 协议挂载在特定的兼容子路径下(例如 /anthropic 或 /api/coding)。但当客户端需要获取该供应商的可用模型列表(GET /models)时,该子路径通常不响应,需要自动剥离并回退到通用根路径:
const KNOWN_COMPAT_SUFFIXES = [
'/api/claudecode',
'/api/anthropic',
'/apps/anthropic',
'/api/coding',
'/claudecode',
'/anthropic',
'/step_plan',
'/coding',
'/claude',
];
export function buildCandidateModelUrls(baseUrl: string): string[] {
const trimmed = baseUrl.trim().replace(/\/+$/, '');
const candidates: string[] = [];
// 1. 若以版本段结尾 (/v1 或 /v4)
if (/\/(v\d+)$/i.test(trimmed)) {
candidates.push(`${trimmed}/models`);
} else {
candidates.push(`${trimmed}/v1/models`);
candidates.push(`${trimmed}/models`);
}
// 2. 命中兼容后缀时剥离并追加纯净根候选
for (const suffix of KNOWN_COMPAT_SUFFIXES) {
if (trimmed.endsWith(suffix)) {
const stripped = trimmed.slice(0, -suffix.length).replace(/\/+$/, '');
if (stripped) {
candidates.push(`${stripped}/v1/models`);
candidates.push(`${stripped}/models`);
}
break;
}
}
return Array.from(new Set(candidates));
}多格式响应解析
探测接口需同时兼容以下主流数据格式:
- OpenAI / Anthropic 标准格式:
{ "data": [{ "id": "model-id", "owned_by": "vendor" }] } - 智谱 Responses 格式:
{ "models": [{ "slug": "model-slug" }] } - 裸模型数组格式:
[ "model-a", "model-b" ]
5. 最短连通性测试设计 (Shortest Connectivity Probe)
传统的全量连通性测试常因生成过长内容而消耗较多 token,或触发过长的等待时间。CC-Switch 演进出的“最短连通性测试”方案具备以下特征:
- 提示词固定为最短指令:
"测试连通,收到回复OK即可"。 - 强制限制最小输出配额:
max_tokens = 16(或max_output_tokens = 16,Responses API 规定不能低于 16)。 - 统一非流式短连接模式:直接利用
stream: false简化回包解析。 核心观测指标:
- HTTP 状态码 (
statusCode)。 - 首包/往返物理延迟 (
latencyMs,使用performance.now()高精度测量)。 - 提取回包纯文本并使用正则
/ok/i校验语义确认度。
- HTTP 状态码 (
6. 三大协议流式抹平状态机 (Multi-Protocol Streaming Transformation)
在 Agent 运行时底层,必须将来自不同协议的 Server-Sent Events (SSE) 统一适配为 Agent 的内部状态流:
flowchart TD
Upstream([上游 API 响应流]) --> Detection{协议判定}
Detection -->|anthropic| AnthropicParser[Anthropic SSE 解码]
Detection -->|openai_responses| ResponsesParser[Responses SSE 解码]
Detection -->|openai_chat| ChatParser[Chat SSE 解码]
AnthropicParser -->|text_delta| OutText[onTextDelta]
AnthropicParser -->|thinking_delta| OutReasoning[onReasoningDelta]
AnthropicParser -->|input_json_delta| OutTool[onToolCallDelta]
ResponsesParser -->|response.text.delta| OutText
ResponsesParser -->|response.reasoning.delta| OutReasoning
ResponsesParser -->|response.function_call_arguments.delta| OutTool
ChatParser -->|delta.content| OutText
ChatParser -->|delta.reasoning_content| OutReasoning
ChatParser -->|delta.tool_calls| OutTool关键细节处理
- 浏览器直连 Anthropic CORS 突破:必须注入请求头
anthropic-dangerous-direct-browser-access: true,否则浏览器内fetch会被服务端拦截。 - Anthropic 连续工具调用回传:多工具并发调用执行完毕后,所有
tool_result必须包裹在同一个role: 'user'消息的 content blocks 中,或严格保证与 assistant 消息交替,切忌出现孤立或非法嵌套。 - Responses API 命名事件匹配:必须同时处理
event:字段或 JSON body 中的type字段(如response.output_item.added)。 - 思考流(Reasoning / Thinking)归一化:将 DeepSeek 的
reasoning_content、Anthropic 的thinking_delta和 Responses API 的response.reasoning.delta统一映射至 Agent 内部的reasoning_content字段并在 UI 中实时展开。
7. 架构取舍:关于 Codex OAuth 与网关边界的评估 (Architectural Tradeoffs)
在本次工程演进中,针对 OpenAI Codex Device OAuth 流程进行了完整的浏览器环境适配与跨域评估,并最终确立了清晰的架构边界:
核心结论
浏览器直接跨域限制 (CORS Barrier):
- OpenAI Codex 后端(
https://chatgpt.com/backend-api/codex)面向终端 CLI 工具设计,并未给第三方 Web 站点开放 CORS 响应头。 - 纯前端 SPA 环境下直接向该端点发起推理请求必定触发浏览器的同源策略拦截。
- OpenAI Codex 后端(
Device Auth 协议特性与浏览器控制台冲突:
- 依据 RFC 8628 规范,客户端在等待授权时轮询 token 端点,OpenAI 官方标准返回 HTTP 403 (deviceauth_authorization_pending)。
- Chrome DevTools 凡接收到 4xx 状态均强制在 Console 输出红字报错,对前端用户造成严重的心智负担和报错误判。
架构收敛决策:
- 若要彻底解决上述问题,必须在本地 Go 网关中构建通用的反向代理与 Session 管理层。
- 为避免在当前阶段引入过重的代理转发与网关复杂化,系统做出果断收敛:暂缓引入 Codex OAuth 流程,保持 Go 网关专注最纯粹的单流透传,所有 Provider 均统一采用标准的 API Key 模式运作。
8. 前端界面层交互集成与落地 (UI Integration & Provider Management)
在 InPage Agent 的设置面板 (app/src/ui/fileTree.ts) 与弹窗 (app/src/ui/providerModal.ts) 中,已将精简高可用的供应商子系统完整落地到用户界面:
设置面板 Provider 管理区:
顶部提供两个快捷操作按钮:
+ 自建 Provider:打开全功能空白供应商新建模态框。+ 从预设添加:快速唤起并预选高质量大厂模版。
供应商卡片列表:
- 展示名称、协议类型徽章 (
OpenAI Chat/Responses/Anthropic)、当前生效标记 (当前生效)、接口 Base URL 与当前默认模型。 - 操作按钮组:
启用(立即切换当前生效源)、测试(卡片内直接触发最短连通性测试并即时显示延迟与状态)、编辑(打开配置弹窗修改)、删除(二次确认后删除自建配置,内置网关受保护)。
- 展示名称、协议类型徽章 (
自建与编辑模态弹窗 (
showProviderModal):- 快捷模版导入:集成 37 个主流大厂预设,选择后自动同步填充 Base URL、协议格式、分类及默认模型。
防误导默认值与严格空 Key 校验:
- 自建 Provider 默认清空 Base URL 与 Model,避免自动填入 DeepSeek 官方地址导致空 Key 触发 401 Unauthorized。
- 连通性测试与模型探测前置拦截:外部供应商若未填 Key 明确提示“外部供应商需先输入 API Key 后再进行连通测试”,阻断无效网络消耗。
模型名下拉与扩展机制:
- 模型下拉选择器 (
select):集中渲染已知与自定义候选模型。 - 动态添加模型名:输入框 +
+ 添加模型名按钮,输入即时注入下拉菜单并设为选中。 - 探测可用模型:一键调用
fetchCandidateModels,自动探测上游/v1/models并智能合并。 - 候选模型 Chip 标签群:支持点击切换当前模型与删除自定义模型项。
- 模型下拉选择器 (
最短连通性测试器 (Shortest Connectivity Test):
- 弹窗内集成连通校验按钮,发送“测试连通,收到回复OK即可”(
max_tokens: 16),直接渲染耗时 (ms)、HTTP 状态码及返回内容,确保保存前验证端点可用性。
- 弹窗内集成连通校验按钮,发送“测试连通,收到回复OK即可”(
本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps