Anthropic Adaptor Streaming 兼容性修复记录
前置条件
中转服务,使用one-api中转连接小米MIMO渠道,渠道类型选择Anthropic,设置好令牌后,局域网其他设备使用这个对外令牌,连接方式也用cc-switch连接,API格式选择OpenAI Chat Completions,并开启路由(cc使用apenai格式必须开启路由,one-api中转对外也必须是openai格式)。但使用claude code开启服务后,发送请求有token消耗,但是界面没有任何输出,查询cc-switch日志发现下述问题。
问题描述
使用 cc-switch 通过 one-api 中转调用 Anthropic Claude 模型时,流式响应报错:
Unknown finish_reason in streaming
根本原因
relay/adaptor/anthropic/main.go 中存在 3 个兼容性缺陷:
stopReasonClaude2OpenAI直接透传未知的 stop_reason --- Claude 返回了 OpenAI 协议中不存在的 finish_reason 值,导致客户端解析失败- 未过滤 thinking 类型的 content block --- Claude 的 extended thinking 返回
thinking/thinking_delta/signature_delta等块,OpenAI 协议不支持这些类型,直接传递会导致客户端异常 - 缺少对控制事件的处理 ---
content_block_stop、message_stop等事件未被识别,进入了默认的响应构建逻辑,产生了无效数据
修复方案
修改文件:relay/adaptor/anthropic/main.go(commit fe82335)
1. 未知 stop_reason 映射为 "stop"
go
// 修复前
default:
return *reason
// 修复后
default:
// unknown stop reason, map to "stop" to avoid client errors
return "stop"
2. 跳过 thinking 类型的 content block
go
// content_block_start 阶段
case "content_block_start":
if claudeResponse.ContentBlock != nil {
+ if claudeResponse.ContentBlock.Type == "thinking" {
+ return nil, nil
+ }
// ...
}
// content_block_delta 阶段
case "content_block_delta":
if claudeResponse.Delta != nil {
+ if claudeResponse.Delta.Type == "thinking_delta" || claudeResponse.Delta.Type == "signature_delta" {
+ return nil, nil
+ }
// ...
}
3. 处理未知控制事件
go
// 修复前:没有 default 分支,控制事件进入响应构建逻辑
// 修复后
default:
// content_block_stop, message_stop and other control events produce no OpenAI chunk
return nil, nil
4. 仅在有 stop_reason 时设置 finish_reason
go
// 修复前
finishReason := stopReasonClaude2OpenAI(&stopReason)
if finishReason != "null" {
choice.FinishReason = &finishReason
}
// 修复后
if stopReason != "" {
finishReason := stopReasonClaude2OpenAI(&stopReason)
choice.FinishReason = &finishReason
}
影响范围
- 仅修改
relay/adaptor/anthropic/main.go一个文件(+15 / -3) - 仅影响 Anthropic → OpenAI 协议转换的流式响应路径
- 不影响非流式调用、不影响其他 adaptor
验证方式
通过 cc-switch 向 one-api 中转发起 Claude 流式调用,确认不再出现 Unknown finish_reason in streaming 错误。Claude code界面也正常有返回内容输出,问题解决。
相关代码已经提交到github源仓库,待通过审核~