Skip to content

chore(sync): 精选 cherry-pick 上游 v0.2.10 并保留 fork 定制 - #275

Merged
ranxi2001 merged 12 commits into
ranxi2001:productionfrom
akihitohyh:sync/upstream-v0.2.10-selective
Oct 2, 2026
Merged

ranxi2001 merged 12 commits into
ranxi2001:productionfrom
akihitohyh:sync/upstream-v0.2.10-selective

Conversation

@akihitohyh

@akihitohyh akihitohyh commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

解决的问题与行为变化

  • 触发条件 / 原行为:上游 v0.2.10(2026-09-29)没有同步过。production 缺少以下改动:Claude Sonnet 5.5 支持;流式用量修正;组合分组 WebSocket 别名路由与模型归属;账号白名单与映射冲突检查;风控白名单;仪表盘花费切换。
  • 修改后行为:按上游合并顺序 cherry-pick 6 个上游 PR 共 11 条提交,每条保留 -x 来源,并保留 fork 现有定制(冲突处理见下表)。主要变化:
    • 支持 claude-sonnet-5-5:模型列表、协议转换、思考强度目录、定价(输入 $2/M、输出 $10/M、缓存写 $2.5/M(1h $4/M)、缓存读 $0.2/M)。
    • 聊天流式响应转发上游已收到的用量;Anthropic 流式用量归一化;延迟缓存场景不再做有歧义的输入扣减。
    • 组合分组下 Responses WebSocket 按组合路由解析别名,连接内切换公开模型名需要重新建连;旧调度路径约束账号模型路由归属。
    • 编辑账号时阻止白名单与模型映射冲突。
    • 新增「风控白名单」设置(cyber_policy_user_allowlist,默认空)。名单内用户:
      • 命中上游 cyber_policy 只记录(cyber_log_only),不写本地会话屏蔽、不计入自动封号、WebSocket 不断开,已有会话屏蔽对其不生效;
      • 本地内容审核同样只记录(risk_control_log_only,动作记为 allow),不拦截请求、不记录违规哈希、不触发封号与通知;
      • 上游拦截照常返回。
    • 仪表盘最近用量可在 token 与花费之间切换。
  • 本次范围与仍未解决的问题:

关联记录与来源

本 PR 提交 上游提交 上游 PR
30c6ec46b feat: support Claude Sonnet 5.5 8490a8186 #7683
2e052e6e5 style: satisfy Sonnet 5.5 lint checks 2cc459e24 Wei-Shaw#7683
3911bf52b feat(dashboard): toggle recent usage between tokens and spending aa3a3ea78 #7646
e1290d54a fix(account): prevent whitelist model mapping conflicts e2c35cf39 #7542
32740b3e5 fix(gateway): resolve composite routes for websocket aliases 13fcfc0f3 #7378
fed355d1a fix(gateway): constrain account model route ownership e878ab710 Wei-Shaw#7378
d508637c7 fix(gateway): enforce composite model ownership in legacy scheduling 453b796df Wei-Shaw#7378
9054a6f4b fix(gateway): forward received chat stream usage b13200d7a #7380
0a2ecb959 fix(gateway): normalize streamed Anthropic usage ece1ecccc Wei-Shaw#7380
11e4a28e0 fix(gateway): avoid ambiguous late-cache input subtraction 0416c9ede Wei-Shaw#7380
553f72565 feat: add risk control user allowlist 6a69dd051 #7679

冲突与适配(全部在对应 cherry-pick 提交内完成,没有单独的整合提交):

交叉点 处理
账号状态、编辑弹窗测试 保留 fork 新增的 BPS 徽章、会话代理、托管工具等用例,加入上游新用例和改名后的标题。
WebSocket 组合路由(13fcfc0f3) handler:保留 fork 首帧的「用户在分组内禁用模型」检查,用上游的组合路由解析替换旧的 ensureCompositeTargetPlatform。ingress:没有采用上游把 BeforeRequest 改用 rawForHash 的部分。fork 的 BeforePayloadParse 预检已经用客户端原始帧判定模型候选,这正是上游此处要修的问题;BeforeRequest 仍用解析后载荷合并解析器注入的能力,并做会话身份与内容审核。上游新增的 7 个组合分组 WebSocket 测试(含「准入使用公开模型名」)全部通过。
「被拒轮次不到达上游」断言 保留 fork 只统计 response.create 的版本。fork 会转发 session.update 等非 turn 帧,不能按通道帧数断言。
旧调度模型归属测试(453b796df) 以 fork 版本为底,追加上游 2 个新测试。fork 的 getOpenAIAccountScheduler 多一个 priority 参数,测试按「高级调度关闭」前提传 false。
风控白名单:设置(6a69dd051) 同时保留 fork 的 cyber_session_identity_strict_enabled 和上游的 cyber_policy_user_allowlist。
风控白名单:运行时缓存 严格身份开关与白名单字段并存。白名单读取失败时沿用上一次的值(上游行为);屏蔽开关读取失败时,严格身份仍按关闭处理(fork 原兜底)。保存设置后保留 fork 的 singleflight Forget 和请求采集配置刷新,并加入上游保留已保存白名单的逻辑。
风控白名单:网关 fork 只按明确会话身份屏蔽,没有上游的正文/转写派生 key。白名单判断改接 fork 的 FindCyberSessionBlockedForIdentity,新 helper 为 findBlockedCyberSessionForIdentity,HTTP 和 WebSocket 共用。WebSocket 连接内屏蔽保留 fork 的本地准入关闭错误。严格会话身份校验对白名单用户照常执行:它是身份协议要求,不属于封号或本地屏蔽。
风控白名单:测试与文案 上游测试 TestCyberAllowlistedUserBypassesExistingBlocksAndContinuesWebSocket 改用明确的 session_id:先验证已屏蔽会话被放行,再验证命中后没有为 WebSocket 会话写入新屏蔽。原版用 prompt_cache_key,在 fork 中不算会话身份,断言会失去意义。i18n 保留 fork 的 cyberSessionBlockHint(明确会话 ID 语义),加入上游白名单文案。
合并 production(e5cd88b3c) production 新增的 502db27d2(来自 #273)和上游 13fcfc0f3 都给 openAIResponsesWSUsageLogCase 加了 closeStatus 字段和可配置的关闭码断言。保留一个字段和 production 的写法,删除多余的默认值赋值,断言内容不变。

复现与验收

  • 环境与基线:production 502db27d2(含 feat(prism): isolate concurrent turns and select account models #269、fix(pelican): 智商测试/鹈鹕测智对 Claude 不再返回为空,并传递思考强度 #271、feat(pelican): 补齐结果 API 管理开关和用户调用信息 #272,以及维护者直接推送的 9699d9ee4、502db27d2)。最初基于 bf9405e4a 完成同步,变基到 eceb5632b 时用 git range-diff 核对 11 条提交全部等价;之后 production 又新增上述两个提交,用合并提交 e5cd88b3c 合入。Go 1.27.0、pnpm 9.15.9,在独立克隆中使用 mock、本地模拟上游和 Docker 集成测试,没有请求生产模型、没有修改运行配置。
  • 前置条件与操作:
    1. Anthropic 分组请求 claude-sonnet-5-5;组合分组用别名建立 Responses WebSocket,第二轮换用其他公开模型名。
    2. 在后台系统设置的「风控」中把用户加入风控白名单,用该用户的 Key 分别触发上游 cyber_policy 和本地内容审核;再用名单外用户对照。
  • 修复前观察:Sonnet 5.5 不在模型列表和定价中;组合分组的 WebSocket 别名不走组合路由;没有白名单设置。
  • 修复后观察 / 验收标准:见「解决的问题与行为变化」。未配置白名单时,原有会话屏蔽、严格身份与内容审核行为不变。
  • 回归测试位置:
    • 上游新增:openai_gateway_ws_composite_test.go(7 个用例)、openai_cyber_allowlist_test.go、risk_control_allowlist_test.go、cyber_policy_allowlist_test.go、setting_cyber_allowlist_test.go、gateway_sonnet55_toolset_beta_test.go,以及调度、流式用量、仪表盘缓存相关用例。
    • fork 原有:严格会话身份、显式会话屏蔽、WebSocket 中继、BPS 等测试全部保留并通过。
    • 未覆盖:真实上游的 Sonnet 5.5 调用与 cyber_policy 命中。
协议、调度或传输改动补充
  • 端点:Anthropic Messages / Chat Completions / Responses(Sonnet 5.5 转换);Responses WebSocket(组合分组)。
  • 流式用量:聊天流转发上游实际收到的 usage,Anthropic 流式 usage 归一化;延迟到达的缓存 token 不再做有歧义的输入扣减。会影响这些路径的用量记录,与上游 v0.2.10 一致。
  • 组合分组 WebSocket:账号、目标平台与路由上下文按连接确定,连接内切换公开模型名会返回需要重新建连的错误,不在连接内重新选路。
  • 风控白名单:不改变重试与故障转移。名单内用户的 cyber_policy 命中只记录、不写屏蔽;上游拒绝照常返回客户端。

实际验证

当前 head:e5cd88b3c(在 553f72565 上合并 production 502db27d2)。

检查与执行目录 / 命令 结果 覆盖范围、证据或未运行原因
backend:go vet -tags=unit ./...、go vet -tags=integration ./... 通过 当前 head
backend:go test -tags=unit -count=1 ./... 通过(以下除外) 当前 head,62 个包通过,覆盖下面「回归测试位置」列出的用例。internal/service 的 TestPriorityOAuthProfitUsesUserChargeAndTheoreticalCost(浮点 3.9999999999999996 ≠ 4)和 internal/reauthruntime 的 TestStopCancelsPreparationAndCannotRestart,在未改动的 production bf9405e4a 与 eceb5632b 上同样失败(本机 macOS arm64)。internal/mihomo 的时序用例只在全量并发时超时,单独运行该包通过。
backend:go test -tags=integration -count=1 ./... 通过(同上) 当前 head,57 个包通过,含 internal/repository(Docker 中的 Postgres / Redis)和 migrations;失败项与上一行相同
backend:golangci-lint v2.13.2 ./... 通过 当前 head,0 issues
backend:go generate ./ent;backend/cmd/server:wire v0.7.0 通过 在 553f72565 上重新生成,与提交内容无差异;合并进来的 production 提交不涉及 ent 和 cmd/server
仓库根目录:make test-frontend 通过 lint:check、typecheck 和关键 Vitest 53 个文件 919 项(553f72565;合并进来的 production 提交只改后端,前端代码与当前 head 相同)
仓库根目录:pnpm --dir frontend run test:run 通过 398 个文件 3,346 项(同上)
仓库根目录:pnpm --dir frontend run build 通过 生产构建(同上)
与 #277 叠加:把两个分支依次合并到 production 502db27d2 通过(同上 1 项) 无文本冲突;go vet、两边都改到的后端包和前端全量检查通过,详见 #277 的验证表。两个 PR 先合哪个都可以。
真实上游 Sonnet 5.5 / cyber_policy 未运行 没有可用于测试的上游账号;不执行付费请求
UI 截图 未提供 仪表盘切换与白名单设置由组件测试覆盖,未在浏览器中渲染
GitHub CI 待运行 以本 PR 当前 head 的 CI 为准

兼容性与运行影响

  • 配置 / API / 默认行为:新增系统设置 cyber_policy_user_allowlist(逗号或空白分隔的正整数用户 ID,默认空,空即关闭;格式不合法时整份拒绝保存),设置接口和 DTO 同步增加该字段。Sonnet 5.5 加入模型列表与定价。组合分组 WebSocket 在连接内切换公开模型名,会改为要求重新建连。
  • 数据库迁移、数据兼容与二进制回滚限制:无迁移。白名单存放在 settings 表;回滚二进制后该设置项被忽略。
  • 权限、凭据脱敏、日志或采集内容:白名单只有管理员可配置,会放宽名单内用户的本地风控,只应加入可信用户(如下游中转站)。名单内用户的事件以 cyber_log_only / risk_control_log_only 记录,不计入自动封号次数;移出名单后,这些历史事件也不会补计(上游设计)。
  • 计费、资源开销、并发或性能:流式用量修正会改变部分请求的用量与计费记录,与上游一致。未做性能测量。
  • 灰度 / 回滚方式与残余风险:白名单默认关闭。残余风险是真实上游的 Sonnet 5.5 与 cyber_policy 行为未实测。

文档与用户可见变化

  • 用户可见:模型列表新增 Claude Sonnet 5.5;系统设置「风控」新增「风控白名单」(按邮箱搜索选择用户);仪表盘最近用量新增 token / 花费切换。
  • 文档:docs/COMPOSITE_GROUPS.md 随上游补充 WebSocket 别名说明。PR 合并不代表已发布或部署。

Agent 使用声明

  • Agent 名称与参与范围:Claude Code(桌面 App Code 页签);差异分析、cherry-pick 与冲突适配、测试、Issue 与本 PR 正文。未使用子 Agent。
  • 模型名称:Claude Opus 5.5(claude-opus-5-5)
  • 推理强度:max

提交前自查

  • base 分支和改动范围正确,没有夹带无关修改。
  • 正文、提交、测试数据和附件不含凭据、ticket/state 或真实用户敏感信息。
  • 实际验证结果已列出,失败、未运行和未覆盖的部分已说明。
  • 已检查配置默认值、权限、兼容性及相关文档;不适用项已说明。
  • Bug 修复有针对性回归验证,或已说明暂时无法补充的原因。
  • 已填写 Agent 使用声明,列出所有参与的 Agent、模型和推理强度;纯人工编写已注明未使用。

🤖 Generated with Claude Code

Production gained 9699d9e and 502db27 (from Wei-Shaw#273). Both this branch
(upstream 13fcfc0) and 502db27 added a closeStatus field to
openAIResponsesWSUsageLogCase and a configurable close-code assertion.
Keep a single field and production's closeStatus local, and drop the
now-redundant tc defaulting block; the assertions are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ranxi2001
ranxi2001 merged commit ea53a4c into ranxi2001:production Oct 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 精选同步上游 v0.2.10:Sonnet 5.5、流式用量、组合分组路由、风控白名单与仪表盘花费

5 participants