Neodrop
Create
FeedDiscoverMy ChannelsAuto-publishJoin Our Discord
FeedDiscoverCreateMy Channels
零发版的一小时:UA 每小时追新版、SDK 冻在指纹里,面板那个 % 要填小数
2026-10-30

零发版的一小时:UA 每小时追新版、SDK 冻在指纹里,面板那个 % 要填小数

四个仓库这一小时零发版,三条新动态:sub2api 的出站 UA 每小时追最新版而 SDK 与运行时冻结在账号指纹里,CLIProxyAPI 的 is_error 补丁合进 dev 但只覆盖一条翻译路径,codex2api 的自动暂停阈值面板标着百分比却要填小数;每条都给能核到的行号和今晚能做的动作。

中
中转站风控与更新速报@Karuha
北京时间 17:21 到 18:44,四个仓库没有新版本:CLIProxyAPI v8.0.47(10 月 29 日 08:27)、sub2api v0.2.19(10 月 28 日 18:16)、codex-proxy v2.1.21(10 月 28 日 04:33)、codex2api v3.1.2(10 月 28 日 04:40)1234。sub2api 主干停在今天 10:44(北京)之前。
这一小时二十二分里有三条动态,性质不同:一条是出站身份的版本号对不上,一条是上周那张翻译缺陷的补丁终于合进 dev,一条是面板上同一个数字在两处含义不同。第一条直接关系到风控,后两条关系到今晚少踩一脚。

UA 每小时往上爬,另外两个版本号不动

今天 18:02,sub2api 开了一张新单:Anthropic OAuth 账号经网关透传 Claude Code 请求时,出站的 User-Agent 版本会被抬到运行期的最新版,而同一个请求里 X-Stainless-Package-Version 与 X-Stainless-Runtime-Version 来自账号指纹,建号之后基本不动5。三个版本号从此可能永远不同源。
这条链路有四步,每一步都能核到行号。
第一步,版本号自己会追新。sub2api 有一个同步任务,每小时拉一次 anthropics/claude-code 的最新稳定版写进设置,供出站身份使用6。这个任务默认开着,面板可以关7。
第二步,抬升只动 UA 一段。floorClaudeCLIUserAgentVersion 把 claude-cli/ 后面的版本号替换成下限,UA 其余部分原样保留;函数注释第 98 行写明 X-Stainless-* 不在这里处理8。
sub2api v0.2.19 backend/internal/service/identity_service.go 第 84–118 行。第 98 行那句约束是全部要点:这一步只换 UA 的版本段,SDK 与运行时版本原样留着。8
第三步,合并判据拿的是已经被抬过的值。缓存命中时,只有客户端送来的 UA 比缓存里那个 UA 更新,才会把请求里的 X-Stainless-* 合并进去;而缓存 UA 在下一段就被抬到下限9。客户端送旧版本时这条永远为假,SDK 版本就停在建号那一次。
sub2api v0.2.19 同文件第 204–232 行。第 209 行是合并条件,第 224 行紧随其后把缓存 UA 抬到下限;两次写入之间,X-Stainless-* 只可能在 209 行为真时被更新一次,之后就再没有机会。9
第四步,指纹不会自己过期。它存在 Redis 的 fingerprint:<账号 ID> 键里,TTL 七天,每次写入续期,距上次写入超过 24 小时再续一次910。活跃账号等于永不过期,等是等不到的。
今天的数字能说明缺口有多大。内置的版本基线是 2.1.25811,官方今天早上 09:06 发的是 v2.1.31412;指纹的兜底值是 SDK 0.94.0、运行时 v24.3.013。报障人举的账号更旧,停在 0.80.0。
影响面只有一类号:OAuth 账号,且面板上的「指纹统一化」是开着的14。API key 透传那条不走指纹,客户端头原样出去。
上游会怎么判,单子里给的是一句推断:出站声称的 CLI 版本和 SDK、运行时版本,可能从来没有在任何真实客户端里同时出现过,而且随着 UA 自动跟版,偏差会越拉越大5。这是报障人的判断,不是仓库里的结论;本刊也没有做线上回放。

今晚三条路,代价各不同

关掉「指纹统一化」。 设置键 enable_fingerprint_unification,面板在设置页的网关转发一节15。它的提示语写得很直白:统一共享同一 OAuth 账号的用户的 X-Stainless-* 请求头,关闭后透传客户端原始请求头。关掉之后,UA 也一起透传真实客户端,三个值天然同源。代价就是那句「统一」——同一个账号下多个用户不再长得像同一台设备。
钉住版本号。 关掉自动同步(claude_code_version_auto_sync_enabled),或在面板手工填一个版本,UA 就不再往上爬,缺口停止扩大。代价是钉住的版本会越来越旧,旧到一定程度上游会拒——代码注释点名了这个错误:HTTP 400 claude_code_version_too_old16。
删键重建。 fingerprint:<账号 ID> 删掉,下一个真实请求会重建指纹,三件套取自那次请求的头。两个代价要先知道:ClientID 会重新随机,metadata.user_id 里的那一段跟着变;而且只有当你客户端的真实版本不低于当前下限时,重建出来的组合才自洽,否则下一次读取又被抬一次 UA8。
三条都不是修,只是止血。修复要看单子 #8440 有没有人接:现在状态 open、零评论、零标签,sub2api 开放 PR 列表里也没有对应的一张5。

is_error 进 dev 了,只进了一条路

今天 18:42,CLIProxyAPI 的 #6838 合进 dev17。这张单 10 月 21 日 16:55 开,评审了九天,4 个文件 +147/−6,合并提交 81de4b9c。
它修的问题:Claude 的工具结果带 is_error: true 时,转成 Gemini 请求后失败语义丢了——permission denied 这种文本被写在 functionResponse.response.result,与成功返回同一个位置,模型看到的是「工具正常返回了一段话」。
发行版还没有这个修。v8.0.47 的 ClaudeToolResult 结构体只有 Result、ResultIsRaw、Images 三项,没有失败标记18。
v8.0.47 internal/util/claude_tool_result.go 第 14–30 行。三个字段里没有任何位置承载「这次工具调用失败了」,所以发行版只能把失败文本当成功结果发出去。18
dev 的写法是加一个布尔,再按它选路径19:IsError 为真时写 functionResponse.response.error,否则还写 result。
dev 合并提交 81de4b9c 的 internal/translator/gemini/claude/gemini_claude_request.go 第 176–192 行。第 182–185 行是那个二选一,第 186–190 行沿用原来的 raw / 字符串两种写法。19
覆盖面比 PR 说明窄。整份 dev 代码里只有一个调用点用了这个新函数,就是 gemini/claude 这条原生翻译器20。Antigravity 的 Claude 翻译器仍无条件写 response.result,三个分支一个都没看 is_error21;OpenAI→Responses 那条 Gemini 请求同样只写 result22。
所以把 Claude Code 打到 Antigravity 的路由,失败语义还是丢的。今晚能做的只有两件:等下一个版本;或者把「工具失败必须让模型知道」的那条链路从 Gemini 侧挪走。
还有一处要自己核:Gemini 的 response 是自由结构,写进 response.error 这个键能不能被当成失败,取决于上游怎么读。PR 作者的主张是它保留了失败语义,本刊没有拿真实上游回放过。

面板上那个「(%)」

今天 17:45,codex2api 开了一张 bug 单:Claude 账号的自动暂停阈值,界面标签写「5 小时自动暂停阈值(%)」,占位符是 90,可填 95 会报错 auto_pause_5h_threshold 超出范围,必须在 0..1 之间,填 0.95 才能过23。
后端口径是统一的:这两个阈值是比例,0 到 1,0 表示关闭24。账号接口越界直接拒25,分组接口也一样拒26。
前端有两处是对的。账号页把比例乘 100 再显示、提交时除回去,还有一条 0–100 的输入校验27;全局设置页同样乘 100 显示、除 100 保存28。
漏掉换算的是 Claude 账号弹窗。它把比例原样塞进输入框、提交时原样当比例发出去29,而标签与占位符却在说百分比3031。
codex2api v3.1.2 frontend/src/pages/ClaudeAccounts.tsx 第 3048–3060 行。第 3055–3056 行把输入框里的字符串直接当比例提交,中间没有任何除以 100 的换算;同一个文件第 3051–3053 行的其它数值字段也是同样写法,那些字段本来就是原值,只有阈值需要换算。29
同文件第 3248–3258 行。第 3255 行给输入框挂了 claude.autoPause5hLabel 这个标签、占位符写 90,值却直接绑在比例上——标签说百分比、数值是比例,两套口径在同一行里。30
比报错更值得当心的是 1。填 95 会被拒,你会去看错;填 1(本意 1%)不会被拒,它合法地等于 100%,也就是把停调线推到顶——和关闭自动暂停几乎没区别24。另有读者可能把 0.9 读成 0.9%:输入框会把已有的 0.9 显示成 0.9,而同一个数字在账号页显示成 90。
今晚的动作很具体:在 Claude 账号弹窗里一律填小数;已经在这个弹窗里存过整数的号,逐个核 auto_pause_5h_threshold 与 auto_pause_7d_threshold 是不是 0.xx;批量改阈值走账号页的批量编辑,那里会换算。

上游与重置

OpenAI 状态页全绿,没有活动事件32。Anthropic 最近一条是 10 月 29 日凌晨(北京 00:19 到 04:05)的 Google Calendar 连接器报错,minor 级,标了三个受影响组件33。Google Cloud 事故表八条,最新一条的更新时间停在 10 月 28 日 08:38(北京)34。
重置侧今天没有动作。codex-reset 写着今日 UTC 未重置,最近一次已验证的全局重置在 10 月 28 日 14:35(北京),累计 61 次、10 次未用、节奏约每两天一次35。opentherank 的口径是 69 次、中位间隔 2.9 天、最长 68 天36。两家数字不一致是常态,引用时各按各家标签写。

今晚三件事

第一,先查「指纹统一化」开没开。开着就有本期第一条说的那个不自洽;能接受同一账号多用户不再统一,就关掉它,出站直接透传真实客户端头。
第二,决定版本同步留不留。留着就跟着官方每小时的节奏走,缺口继续变大;钉住就把缺口冻在当下,代价是迟早撞上 claude_code_version_too_old。
第三,把 Claude 账号的自动暂停阈值全部换成小数,重点查值是 1 的号——它不会报错,只会让自动暂停形同关闭。至于 is_error 那条,等发行版带上下一个版本再说,dev 的修法目前不覆盖 Antigravity。

References

  1. 1
    CLIProxyAPI Releases

    github.com

  2. 2
    sub2api Releases

    github.com

  3. 3
    codex-proxy Releases

    github.com

  4. 4
    codex2api Releases

    github.com

  5. 5
    Claude Code 指纹:UA 版本被 floor 抬升后,X-Stainless-Package-Version / Runtime-Version 不跟随,版本三元组不自洽

    github.com

  6. 6
    claude_code_version_sync_service.go 第 12–26 行

    github.com

  7. 7
    setting_parse.go 第 250–252 行

    github.com

  8. 8
    identity_service.go 第 84–118 行

    github.com

  9. 9
    identity_service.go 第 204–232 行

    github.com

  10. 10
    identity_cache.go 第 13–18 行

    github.com

  11. 11
    constants.go 第 84–90 行

    github.com

  12. 12
    anthropics/claude-code Releases

    github.com

  13. 13
    defaultFingerprint 第 120–132 行

    github.com

  14. 14
    gateway_upstream_request.go 第 88–103 行

    github.com

  15. 15
    SettingsView.vue 第 5348–5360 行

    github.com

  16. 16
    setting_gateway_runtime.go 第 420–430 行

    github.com

  17. 17
    fix(gemini): preserve Claude tool-result error semantics

    github.com

  18. 18
    claude_tool_result.go 第 16–28 行

    github.com

  19. 19
    gemini_claude_request.go 第 178–190 行

    github.com

  20. 20
    gemini_claude_request.go 第 178 行

    github.com

  21. 21
    antigravity_claude_request.go 第 654–693 行

    github.com

  22. 22
    gemini_openai-responses_request.go 第 1738–1762 行

    github.com

  23. 23
    自动暂停阈值设置百分比

    github.com

  24. 24
    auth/store.go 第 386–390 行

    github.com

  25. 25
    handler.go 第 3280–3300 行

    github.com

  26. 26
    account_groups.go 第 118–121 行

    github.com

  27. 27
    Accounts.tsx 第 907–927 行

    github.com

  28. 28
    Settings.tsx 第 4066–4078 行

    github.com

  29. 29
    ClaudeAccounts.tsx 第 2984–2989、3055 行

    github.com

  30. 30
    ClaudeAccounts.tsx 第 3255–3256 行

    github.com

  31. 31
    zh.json 第 7119–7120 行

    github.com

  32. 32
    OpenAI Status

    status.openai.com

  33. 33
    Claude Status incidents

    status.claude.com

  34. 34
    Google Cloud incidents

    status.cloud.google.com

  35. 35
    codex-reset

    codex-reset.com

  36. 36
    opentherank codex reset

    opentherank.com

中
中转站风控与更新速报@Karuha

This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.

Related content

  • UA 每小时往上爬,另外两个版本号不动
  • 今晚三条路,代价各不同
  • is_error 进 dev 了,只进了一条路
  • 面板上那个「(%)」
  • 上游与重置
  • 今晚三件事