Skip to content

chore(sync): sync upstream v0.1.171 into develop - #16

Merged
lien0219 merged 321 commits into
mainfrom
develop
Aug 7, 2026
Merged

chore(sync): sync upstream v0.1.171 into develop#16
lien0219 merged 321 commits into
mainfrom
develop

Conversation

@lien0219

@lien0219 lien0219 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

概述

本 PR 将 sync-upstream 分支中已经完成三方语义合并的官方最新代码,同步合并到 develop

本次上游同步范围:

  • 上游仓库:Wei-Shaw/sub2api
  • 上游版本:v0.1.171
  • 上游基准提交:93367b6db43315abe4f9fd9b09cbfc971b1f5ad0
  • 本地上游镜像分支:upstream-main
  • 三方合并分支:sync-upstream
  • 同步范围:v0.1.164 → v0.1.171
  • 上游新增提交:约 318 commits
  • 本次合并涉及:704 个文件

合并策略

本次不是简单采用 ours/theirs,而是在 sync-upstream 分支完成生产级三方语义合并。

核心原则:

  • 保留 ModuRelay 已有二开功能
  • 保留 ModuRelay 品牌、UI、部署及 CI/CD
  • 吸收官方 v0.1.171 新功能、Bug 修复、安全修复及性能优化
  • 底层 Gateway、协议兼容、调度、缓存、OAuth 等核心能力尽量跟随官方最新实现
  • 对双方同时修改的代码进行人工语义合并,避免二开能力被官方代码覆盖

冲突处理

本次共处理 15 个显式冲突文件,主要包括:

  • README 多语言文档
  • 后端配置与 Setting 解析
  • frontend/package.json
  • pnpm-lock.yaml
  • AccountBulkActionsBar.vue
  • AnnouncementPopup.vue
  • AppHeader.vue
  • HomeView.vue
  • AccountsView.vue
  • EmailVerifyView.vue
  • RegisterView.vue

另外审计了双方共同修改但 Git 自动合并的文件,确认未发现明显的二开功能静默丢失。

ModuRelay 保留内容

本次同步继续保留:

  • ModuRelay 品牌及 Logo
  • Three.js / GSAP 3D 首页
  • 首页自定义交互与主题
  • AppHeader 二开 UI
  • 用户菜单及版本号显示
  • ModuRelay 自定义 i18n
  • 自定义 CI/CD 与生产部署配置
  • 用量详情隐私控制

包括以下设置链路:

  • AllowUserViewErrorRequests
  • UsageDetailShowUnitPrices
  • UsageDetailShowRateMultiplier
  • UsageDetailShowOriginalCost

吸收的官方能力

本次同步吸收官方 v0.1.171 的主要更新,包括但不限于:

  • Passkey
  • 腾讯云 / 阿里云验证码
  • Turnstile 相关安全流程
  • 紧凑首页
  • 模型广场
  • 账号全量批处理
  • OpenAI Live
  • WebSocket
  • Responses API 兼容增强
  • Chat Completions / 多协议兼容
  • OAuth 更新
  • Scheduler / Failover
  • Profit Control
  • Panel Rate Limit
  • Gateway 缓存优化
  • 数据库迁移
  • 安全及稳定性修复

验证结果

已完成:

  • 15 个 merge conflict 全部解决
  • gofmt
  • go test ./...
  • pnpm lockfile 校验
  • pnpm run lint:check
  • pnpm run typecheck
  • Vitest 全量测试
  • pnpm run build
  • git diff --check
  • git diff --cached --check
  • 无残余 merge conflict marker
  • 前后端构建及测试通过

前端构建仅存在既有的 chunk 大小及动态/静态 import 警告,不影响构建通过。

尚未进行的生产环境验证

以下能力需要合并至 develop 后继续进行实际环境冒烟测试:

  • OAuth
  • 腾讯云 / 阿里云 Captcha
  • Passkey
  • 支付
  • PostgreSQL 数据库迁移
  • API Gateway
  • SSE / Streaming
  • WebSocket / OpenAI Live
  • 上游账号调度及 Failover

Merge Commit

本次上游三方合并提交:

34d59982d7bdd8582b10086cad264aaa0251bfea3

其两个 parent 分别对应:

  • ModuRelay 二开基线
  • 官方 sub2api v0.1.171

确保 Git 保留完整上游同步历史,便于后续继续增量同步官方代码。

wucm667 and others added 30 commits July 26, 2026 16:26
 1. harden OpenAI compatibility forwarding
 2. reject usage-only non-stream responses
Manual Grok connection tests previously surfaced upstream HTTP 402 errors without changing account availability. Persist the same 30-minute payment-required cooldown used by the live forwarding path so refreshed account lists no longer present the account as schedulable.

Constraint: Keep manual-test HTTP 402 handling aligned with existing Grok forwarding semantics.
Rejected: Mark the account permanently error | payment state can recover and the forwarding path intentionally uses a bounded cooldown.
Confidence: high
Scope-risk: narrow
Directive: Keep the manual-test cooldown reason and duration aligned with handleGrokAccountUpstreamError.
Tested: go test -tags=unit ./internal/service -count=1; go vet -tags=unit ./internal/service; production package compile check
Not-tested: Live xAI account with an exhausted subscription
Related: #4794
…prompt cache

When an upstream API gateway (e.g. new-api) relays real Claude Code
requests, the User-Agent becomes Go-http-client while the body retains
the full Claude Code fingerprint (billing attribution block +
metadata.user_id + cache_control breakpoints).

Previously, the OAuth mimicry path relied solely on UA matching to
detect Claude Code clients. Without a matching UA, the gateway would
rewrite the system prompt — replacing the client's carefully structured
system blocks and cache_control breakpoints with its own injection.
This breaks Anthropic's prefix-based prompt cache: since the cache key
evaluates tools → system → messages in order, a changed system
invalidates all downstream message caching.

Symptoms observed:
- cache_read permanently locked at ~25K (only system prompt cached)
- cache_creation growing monotonically every turn (full messages rewrite)
- Single-request costs $17-27 instead of normal $1-2

Fix: when UA does not match but the body contains a valid billing
attribution block (x-anthropic-billing-header with cc_entrypoint=),
treat the request as proxied Claude Code traffic and skip mimicry.
This preserves the client's original system structure and cache_control
breakpoints, allowing Anthropic's prompt cache to function correctly.
Make CONFIG_FILE select an explicit config for both full loading and lightweight address lookup, with regression tests.
Namespace tool flatten/restore, array function_call_output, omit empty input_schema for native tools, lift additional_tools; scoped to ForwardAsResponses.
MonitorTimeline 每根柱子设置了 min-w-[3px],60 根柱子加 2px 间距的
最小总宽度为 298px。当卡片内容区宽度低于该值时(如 100% 缩放下的
部分布局),时间线整体溢出卡片边缘。改为 min-w-0 让柱子随容器等分
压缩,任意宽度下均不再溢出。
fix(grok): pause accounts after manual test payment failure
…-overlap

fix: show optional affiliate code on registration
…-channels

fix(frontend): adapt available channels for mobile
…fig-load

fix(security-audit): reject unavailable prompt config
…fering

fix(deploy): prevent Caddy compression from buffering SSE
fix(frontend): 修复渠道监控时间线在窄卡片下溢出
…-2.1.220

fix(claude): 伪装的 Claude Code CLI 版本号升级到 2.1.220
…break

fix(gateway): 识别被代理的 Claude Code 流量,避免 mimicry 重写破坏 prompt cache
Wei-Shaw and others added 29 commits August 4, 2026 16:15
fix(oauth): use claude.com/cai authorize endpoint
fix(grok): bump pinned Grok CLI version to 0.2.114
fix(model-plaza): Model Plaza image model price display is inconsistent with the actual price
fix(openai-ws): preserve terminal event on lease loss
…n-renewal

fix(subscription): serialize concurrent renewals
…raffic

The account+model transient breaker reset its failure streak whenever the
gap since the previous failure exceeded a one-minute window. That made the
breaker's sensitivity a function of request rate rather than upstream
health: a gateway called less often than once a minute never advanced past
streak 1, where the cooldown is zero, so a consistently broken account was
never blocked. Every request re-selected it, paid a full upstream attempt,
and only then failed over to a healthy account.

Observed on a low-traffic deployment: two accounts returning 500 and 503
stayed in rotation indefinitely, logging `failure_streak: 1, cooldown_ms: 0`
on every request and adding ~750ms to each one before a working account was
reached.

The streak is already cleared on success — recordSuccess deletes the entry,
and every OpenAI handler reports the schedule result — so the time-based
reset is not needed to recover a healthy account. Keep a TTL purely to bound
the map for account+model pairs that stopped being used, and raise it well
above the cooldowns so it no longer doubles as a streak reset.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#5261 added a captcha check to POST /auth/oauth/pending/create-account, but
the shared create-account form only gates its send-code button on the
Turnstile token — the submit button's disabled condition never included it.

Turnstile tokens are single-use, so handleSendCode resets the widget in its
finally block and clears the token. Submitting inside the window before the
widget re-solves omits turnstile_token from the payload, and the backend
answers ErrTurnstileVerificationFailed (turnstile_service.go:65). With an
interaction-required challenge the widget does not re-solve on its own, so
the failure persists until the user notices and verifies again — while the
button stays enabled and says nothing.

Gate the submit button on the token, mirroring the send-code button and
EmailVerifyView, which already gates its pending-OAuth submit the same way.
handleSubmit repeats the check because implicit form submission (Enter in a
text input) bypasses the button's disabled state.

The Tencent path is unaffected: handleSubmit already acquires a fresh proof
per submit, and turnstile_enabled is false in that configuration.

Verified with the component spec (11 passed) and vue-tsc --noEmit (clean).
…it-gate

fix(auth-ui): 第三方 OAuth 建号提交前必须持有验证码票据
沿用腾讯天御验证码引入的多服务商模型:aliyun_captcha_enabled 作为独立
开关,与 Cloudflare Turnstile、腾讯天御三方互斥(保存校验 + 运行时
CAPTCHA_PROVIDER_CONFLICT)。后台「安全与认证」合并为单张人机验证卡片:
总开关 + 服务商单选(Turnstile / 腾讯天御 / 阿里云),选中即启用该家并
关闭其它,落库仍是三个独立开关键,由前端映射保证互斥。

阿里云侧同时支持 aliyun 中国站与国际站(alibabacloud.com):两站前端脚本、
region 取值与服务端 API 完全一致,仅账号与 AccessKey 相互独立,因此由
「服务地域」决定线路即可——中国内地走 captcha.cn-shanghai.aliyuncs.com,
非中国内地(新加坡)走 captcha.ap-southeast-1.aliyuncs.com,AccessKey
取自持有该实例的账号,无需在配置中区分站点。

- AliyunCaptchaService 对称 TencentCaptchaService:服务端校验走官方 SDK
  VerifyIntelligentCaptcha,调用异常按 fail-closed 拦截,与 Turnstile
  网络错误行为对称;保存设置时真实探测 AK/SK 有效性
- 保护面对齐腾讯扩展入口:VerifyTencentCaptchaIfEnabled 通用化为
  VerifyActionCaptchaIfEnabled,OAuth 登录启动、passkey 登录在阿里云
  启用时同样拦截;Turnstile 维持既有覆盖不扩大
- 前端 AliyunCaptchaWidget 为表单内预验证按钮(popup 模式),同时暴露
  verify() 供 OAuth 启动、passkey 等动作入口程序化弹窗;未预验证直接
  提交时弹窗兜底。SDK 按钮绑定异步完成,弹窗未出现前按 tick 重试触发,
  并轮询弹窗可见性识别用户关闭
- captchaVerifyParam 复用 turnstile_token 请求字段提交;公开设置下发
  aliyun_captcha_enabled / scene_id / prefix / region
- CSP 放行验证码 CDN:script-src/style-src 加 *.alicdn.com
feat(aliyun-captcha): 人机验证增加阿里云验证码 2.0
…ary-scale

fix(billing): quantize usage billing amounts to the NUMERIC(20,8) scale
fix(payment): preserve UTF-8 in EasyPay errors
…dence

fix(openai): keep transient failure streak from resetting on sparse traffic
修复国内站和国际站 SDK 构造、验证容器、票据重置及动态资源加载问题,并补充认证流程回归测试。
修复腾讯验证码区域适配、重置与 CSP 加载
fix(openai): default OAuth identity to codex-tui
chore(sync): sync upstream v0.1.171 into develop
- sync upstream changes through sub2api v0.1.171
- preserve ModuRelay custom features and branding
- update dependencies, lockfile, tests, and build assets
- resolve all upstream merge conflicts
@lien0219
lien0219 merged commit 1cb1777 into main Aug 7, 2026
14 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.