Skip to content

fix(gateway): resolve composite routes for websocket aliases - #7378

Open
wucm667 wants to merge 2 commits into
Wei-Shaw:mainfrom
wucm667:fix/issue-7368-composite-ws-routing
Open

wucm667 wants to merge 2 commits into
Wei-Shaw:mainfrom
wucm667:fix/issue-7368-composite-ws-routing

Conversation

@wucm667

@wucm667 wucm667 commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

问题

合成分组的显式模型别名在 HTTP 请求可用,但 WebSocket 首帧仅按模型名称判断目标,导致合法路由被拒绝。

改动

  • 首帧复用路由解析器,支持 responses 与 any 路由及上游模型映射,保留既有平台限制。
  • 以公开模型执行准入和展示,按路由、渠道、账号顺序处理映射,保持计费口径。
  • 后续帧继续使用公开模型检查;切换合成模型需重新连接,避免连接级账号与目标错配。
  • 添加路由、拒绝路径、多轮、计费回归和文档。

验证

已验证:后端完整单元与集成测试、静态检查、安全扫描,前端 lint、类型检查、关键测试与依赖安全审计,前后端构建及部署脚本测试全部通过。独立复核通过。
部署脚本的系统专有命令在本地使用兼容适配;未使用真实上游账号进行外部请求验证。
重复检查:未发现等价实现;现有 #5013 明确不处理首帧路由。

Fixes #7368

@Wei-Shaw

Copy link
Copy Markdown
Owner

代码审查(基于 b9da510f0409ece8bfb13e3643018e1c2372b9c9):显式合成路由的主流程成立,但发现一项需要合并前修复的 P2 正确性问题:账号归属回退没有约束后续选号

首帧现在调用完整 CompositeRouteResolver.Resolve,同时启用了 source=account_model 的回退;生产 Wire 使用的共享 resolver 已由 GatewayService 注入 resolveCompositeModelOwnership,所以这条路径实际可达。

触发配置:

  1. 合成组内有两个支持 Responses WS 的 OpenAI API Key 账号 A、B,无显式路由和渠道改名。
  2. A 配置 model_mapping={"team-alias":"gpt-5.4"},B 没有模型映射。
  3. 客户端首帧使用 team-alias,分组白名单允许该名称。
  4. resolver 根据 A 确定目标平台 OpenAI,但专用调度器只检查 IsModelSupported(team-alias)。B 的空映射允许全部模型,因此 B 仍可因粘性、优先级或负载被选中。
  5. B 的 GetMappedModel 返回原始 team-alias,请求以 B 的凭据和未转换的别名发送上游,可能返回模型不存在,或执行 B 上含义不同的同名模型。

证据:

此前未知 team-alias 会被 WS 的 detector 路径拒绝;本 PR 新接入完整 resolver 后才打开上述错误调度场景。显式路由本身不受这个 fallback 问题影响,也没有证据支持把它描述为跨租户越权。

建议在 source=account_model 时,将 RequestedPublicModel 的精确归属约束放入 OpenAI 共用候选校验,并覆盖初筛、粘性命中、最新账号复核和 failover。不要直接固定成 A 的上游模型,因为不同 owner 可能有不同账号映射。请补充实际 ownership resolver + A/B 混合池(含非 owner 粘性命中)的回归;现有单账号显式路由用例覆盖不到此问题。

以上为静态调用链推导并经独立复核,本次审查未重复运行测试。

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.

[问题] composite 路由表是否刻意不适用于 Responses WebSocket?路由目标为 grok 的模型在 WS 上被拒绝

2 participants