问题描述
在服务商配置界面,对使用 Anthropic 协议的第三方代理(如 gaccode.com)进行测试连接和更新配置时都会失败,但实际对话却能正常走通。
复现步骤
- 添加 Anthropic Third-party API 服务商,填入 base_url(如 https://gaccode.com/claudecode)和 API key
- 点击测试连接 → 失败
- 尝试编辑并保存已配置好的服务商 → 失败
- 但其他以前配好了服务的旧版CodePilot直接升级后,只要不碰这个服务商的配置,直接发起对话,模型工作正常 ✅
根因分析
问题 1:测试连接使用了模型别名
testProviderConnection 函数的模型名解析链:
modelName → preset.defaultRoleModels.default → preset.defaultModels[0].upstreamModelId → preset.defaultModels[0].modelId → "sonnet"
anthropic-thirdparty 预设的 defaultModels(变量 t,与 openrouter / litellm 共用)没有设置 upstreamModelId:
// 变量 t
[
{ modelId: "sonnet", displayName: "Sonnet 4.6", role: "sonnet", ... },
{ modelId: "opus", displayName: "Opus", role: "opus", ... },
{ modelId: "haiku", displayName: "Haiku 4.5", role: "haiku", ... },
]
// 注意:全都没有 upstreamModelId!
因此测试连接最终发送 {"model": "sonnet"} 到第三方代理。
但第三方代理(gaccode 等)不支持 Anthropic 的模型别名(sonnet/opus/haiku),只认完整模型 ID(如 claude-sonnet-4-20250514)。
实测验证:
| model 值 |
HTTP 状态 |
响应 |
"sonnet" (别名) |
500 |
No claude account available |
"opus" (别名) |
500 |
No claude account available |
"haiku" (别名) |
500 |
No claude account available |
"claude-sonnet-4-20250514" (完整ID) |
200 ✅ |
pong |
"claude-opus-4-20250514" (完整ID) |
200 ✅ |
pong |
"claude-haiku-4-5-20251001" (完整ID) |
200 ✅ |
pong |
问题 2:更新时 base_url 空字符串校验
PUT handler 的验证逻辑:
const baseUrl = body.base_url !== undefined ? body.base_url : existing.base_url;
if (protocol === "anthropic" && !baseUrl?.trim()) {
return { code: "ANTHROPIC_BASE_URL_REQUIRED" };
}
当前端表单提交 base_url: ""(空字符串而非 undefined)时,body.base_url !== undefined 为 true,触发此错误,即使该服务商原本已有有效的 base_url。
为什么实际对话能通?
detectTransport 对非 api.anthropic.com 的 base_url 返回 claude-code-compat 传输层,实际对话走 SDK 子进程,直接使用用户在 UI 中选择的完整模型 ID,不经过别名转换。
建议修复
修复 1(测试连接)
方案 A(快速):为第三方预设的 defaultModels 补充 upstreamModelId。但这不完美——第三方代理不一定托管所有官方模型,别名映射到错误模型也可能失败。
方案 B(根本):在测试连接界面提供模型输入框,让用户可以指定用哪个模型进行连通性测试,而不是硬编码推断。
修复 2(更新校验)
将空字符串 "" 等同于 undefined 处理:
const baseUrl = body.base_url || existing.base_url;
影响范围
- 所有使用
anthropic-thirdparty 预设的第三方 Anthropic 代理(gaccode、LiteLLM、Ollama 等)
openrouter / litellm 预设也可能受影响(共用同一组 t 默认模型)
本 issue 基于客户端源码分析 + curl 实测验证。
问题描述
在服务商配置界面,对使用 Anthropic 协议的第三方代理(如 gaccode.com)进行测试连接和更新配置时都会失败,但实际对话却能正常走通。
复现步骤
根因分析
问题 1:测试连接使用了模型别名
testProviderConnection函数的模型名解析链:anthropic-thirdparty预设的defaultModels(变量t,与 openrouter / litellm 共用)没有设置 upstreamModelId:因此测试连接最终发送
{"model": "sonnet"}到第三方代理。但第三方代理(gaccode 等)不支持 Anthropic 的模型别名(sonnet/opus/haiku),只认完整模型 ID(如 claude-sonnet-4-20250514)。
实测验证:
"sonnet"(别名)"opus"(别名)"haiku"(别名)"claude-sonnet-4-20250514"(完整ID)"claude-opus-4-20250514"(完整ID)"claude-haiku-4-5-20251001"(完整ID)问题 2:更新时 base_url 空字符串校验
PUT handler 的验证逻辑:
当前端表单提交
base_url: ""(空字符串而非 undefined)时,body.base_url !== undefined为 true,触发此错误,即使该服务商原本已有有效的 base_url。为什么实际对话能通?
detectTransport对非 api.anthropic.com 的 base_url 返回claude-code-compat传输层,实际对话走 SDK 子进程,直接使用用户在 UI 中选择的完整模型 ID,不经过别名转换。建议修复
修复 1(测试连接)
方案 A(快速):为第三方预设的
defaultModels补充 upstreamModelId。但这不完美——第三方代理不一定托管所有官方模型,别名映射到错误模型也可能失败。方案 B(根本):在测试连接界面提供模型输入框,让用户可以指定用哪个模型进行连通性测试,而不是硬编码推断。
修复 2(更新校验)
将空字符串
""等同于undefined处理:影响范围
anthropic-thirdparty预设的第三方 Anthropic 代理(gaccode、LiteLLM、Ollama 等)openrouter/litellm预设也可能受影响(共用同一组t默认模型)本 issue 基于客户端源码分析 + curl 实测验证。