Wesley Liddick
3045b3ade1
Merge PR #6316
...
fix(openai): honor Claude Code session id for messages sticky routing
2026-08-29 09:03:14 +08:00
Wesley Liddick
604360d1cc
Merge PR #6328
...
fix(frontend): 批量编辑显式提交 codex_fingerprint_mode=off,修复无法关闭指纹收敛
2026-08-29 09:02:25 +08:00
Wesley Liddick
25dc5742ea
Merge PR #6332
...
fix(monitor): 配额抓取在 singleflight 执行体内重查缓存,消除重复上游查询
2026-08-29 09:01:15 +08:00
Wesley Liddick
1136e290fd
Merge PR #6334
...
fix(payment): show selected currency in recharge rate
2026-08-29 09:01:06 +08:00
Wesley Liddick
6506c0ea68
Merge PR #6343
...
fix(gateway): preserve Anthropic tool arguments
2026-08-29 09:00:56 +08:00
Wesley Liddick
1323d1645d
Merge PR #6346
...
fix(keys): preserve Claude attribution headers
2026-08-29 09:00:46 +08:00
Wesley Liddick
f1d845c630
fix(grok): honor prompt cache key for side calls
...
fix(grok): honor client prompt_cache_key over X-Grok-Conv-Id so grok-build side-calls share the main-turn cache
2026-08-29 09:00:06 +08:00
RayWangX
5688bcba91
fix(openai): honor Claude Code session for messages sticky routing
2026-08-29 08:31:15 +08:00
风起
88cb79d8b3
fix(grok): honor client prompt_cache_key over X-Grok-Conv-Id for cache identity
...
grok-build CLI recap-style side-calls (turn-summary / title-refresh) send
a fresh per-call X-Grok-Conv-Id label but set body prompt_cache_key to
the parent session id, so a direct xAI connection shares the main turn's
server-side prompt cache prefix.
sub2api's explicitGrokCacheSeed preferred X-Grok-Conv-Id over the body
key, which fragmented the cache identity on every side-call and forced a
full-price replay of the whole conversation (~300K+ tokens each, ~2.3%
cache hit rate observed over 44 side-calls / 4.9M input tokens in 7
days — about a third of all grok-4.6 input).
Priority is now: CC session > generic session headers > body
prompt_cache_key > X-Grok-Conv-Id > explicitKey > previous_response_id.
IDE header-stability tests updated; new regression test locks in the
side-call/parent key-sharing contract.
2026-08-28 21:56:22 +08:00
wucm667
c037766040
fix(keys): preserve Claude attribution headers
2026-08-28 20:42:58 +08:00
wucm667
da10822d7d
fix(gateway): preserve Anthropic tool arguments
2026-08-28 19:08:26 +08:00
wucm667
02eee39ddf
fix(payment): show selected currency in recharge rate
2026-08-28 16:54:33 +08:00
li
e652f6e20a
fix(monitor): 配额抓取在 singleflight 执行体内重查缓存,消除重复上游查询
...
ChannelMonitorQuotaFetcher.Fetch 顶部的 cachedSnapshot 与随后的 flight.DoChan
之间存在一个窗口:goroutine A 判定缓存未命中之后、真正入队之前,goroutine B 的
flight 可能已经跑完、写好缓存,并且它的 singleflight key 也已被摘掉。A 于是不会
并入 B 的那次飞行,而是另起一个新 flight,对同一账号再打一次上游——正是
singleflight 想要消除的重复查询。
多个监控可以关联同一账号,interval 最小 15s,国产配额服务自身无缓存,
这条路径的全部意义就是防止打爆上游配额端点(见文件头注释)。
修复:把 flight 执行体提为具名方法 fetchShared,开头重查一次缓存。
这次重查必然命中,所以合并是确定的而非尽力而为:storeSnapshot 发生在执行体
返回之前,singleflight 删 key 发生在返回之后,因此「能新起一次飞行」必然蕴含
「上一次的快照已经可见」。
该窗口也是主线 CI 上 TestQuotaFetcher_ConcurrentFetchesShareSingleFlight
间歇性失败(expected: 1, actual: 2)的成因,本地 -count=900 复现 3 次(约 0.33%),
带修复后 -count=1700 零失败。
新增两条确定性用例:既有并发用例只能以约 1/300 的概率撞上该窗口,故直接钉住
窗口本身——fetchShared 就是 flight 的执行体,直接调用它等价于「已越过顶层缓存
判定、拿到属于自己的那次飞行」这一状态。另一条守住重查不得退化成无条件短路:
缓存过期后必须照常回源。
2026-08-28 16:49:49 +08:00
li
0756c98102
fix(frontend): 批量编辑显式提交 codex_fingerprint_mode=off,修复无法关闭指纹收敛
...
批量编辑选「关闭(默认)」时,buildUpdatePayload 先 ensureExtra() 建出 extra
再 delete 掉唯一的键,payload 退化成 {account_ids, extra:{}},被后端
len(req.Extra) > 0 判为空更新,直接 400 "No updates provided";device/session/full
则正常。即便后端放行空 extra 也无济于事:批量更新走 JSONB 顶层合并
(extra = COALESCE(extra,'{}') || payload),删掉 payload 里的键只表示
「本次不更新该键」,清不掉账号上已有的 device/session/full。
根因是把 Create/Edit 的写法直接搬到了 Bulk:那两个表单提交完整 extra 对象、
后端 SetExtra 整体覆盖,删键确实等于清除;批量接口只合并增量键,两种持久化
语义不能共用同一套写法。
改为 off 也显式落键,与本函数里其它「关闭/清除」字段一致——codex_cli_only
直接落 false(EditAccountModal 相邻注释已写明「关闭时显式写 false,避免 extra
为空被后端忽略导致旧值无法清除」)、load_factor 落 0、proxy_id 落 0。
读取侧完全等价,不改变 #5610 定下的语义:codexFingerprintModeFromExtra 对
空值/非法值走 default 回落 off,对 "off" 命中同一分支;
ShouldEnsureCodexFingerprintSeedForExtraUpdates 也只在 device/session/full
时要种子,显式 off 不会触发种子创建。
顺带给「编辑该项」勾选框补 id(同区域 Select 早有 data-testid,兄弟开关
codex_cli_only 也有 id),否则新增用例无法定位该控件。
新增 3 条用例:主复现(默认 off + 勾选编辑 ⇒ 提交 codex_fingerprint_mode=off,
并断言 extra 非空以钉死 400 那个形状)、显式 opt-in 仍原样提交、未勾选时不写入该键。
Fixes #6327
2026-08-28 16:20:14 +08:00
Wesley Liddick
7b693ae429
Merge pull request #6188 from JialinLiu-codedance/feat/usage-requested-reasoning-effort
...
feat(usage): 使用记录展示映射前的推理强度
2026-08-28 16:18:50 +08:00
Wesley Liddick
d4754c211a
Merge pull request #6291 from Whisper-stark/fix/grok-codex-responses
...
fix(grok): sanitize Codex Responses requests
2026-08-28 15:58:39 +08:00
Wesley Liddick
423f895755
Merge pull request #6227 from OG-Wang/codex/promo-code-oauth-signup
...
fix(auth): pass registration promo codes to OAuth signup
2026-08-28 15:58:09 +08:00
Wesley Liddick
c8a6e93f33
Merge pull request #6310 from fengshao1227/fix/nonstreaming-terminal-failure-failover-v2
...
fix(openai): 非流式路径按流式同一套判定处理 HTTP 200 终止失败事件
2026-08-28 15:57:39 +08:00
Wesley Liddick
446042e518
Merge pull request #6309 from fengshao1227/fix/easypay-resolve-relative-payurl-qrcode
...
fix(payment): EasyPay 补全 mapi.php 回传的相对 payurl/qrcode
2026-08-28 15:57:10 +08:00
Wesley Liddick
1e6926cb9c
Merge pull request #6312 from fengshao1227/fix/openai-ws-client-close-not-account-failure
...
fix(openai): 入站 WS 的客户端正常关闭与断开不再计为账号故障
2026-08-28 15:56:34 +08:00
Wesley Liddick
e866ff6ec4
Merge pull request #6303 from akihitohyh/feat/per-user-public-group-access
...
feat(admin): 支持为单个用户限制可访问的公开分组
2026-08-28 13:19:11 +08:00
li
c83dced4ba
fix(openai): 入站 WS 的客户端正常关闭与断开不再计为账号故障
...
ingress WebSocket 收尾处只把 *service.OpenAIWSClientCloseError 且状态码为 1000
的情况认作正常关闭,其余全部落到 shouldReportOpenAIWSProxyAccountFailure ——
而它只排除 model-switch 与 session-preempted 两种。两种完全正常的结束因此被
误判为上游/账号故障:
- 客户端干净关闭:coder/websocket 直接回裸 coderws.CloseError{Code: 1000},
ReadOpenAIWSClientMessage 把 conn.Read 的错误原样返回,没有任何一层把它包成
*OpenAIWSClientCloseError,所以 errors.As 对该类型必然为假。
- 客户端中途断开:ReadOpenAIWSClientMessage 在 controlCtx.Done() 分支用
StatusGoingAway(1001) 收尾并以 context.Canceled 为 cause,「只认 1000」匹配不到。
两者都会走到 ReportOpenAIAccountScheduleResult(success=false),进而喂给
ObserveOpenAIAPIKeyHealthFailure 与 scheduler.ReportResult,累积到阈值即把上游
账号熔断出调度池——客户端按一次 Ctrl-C 就在扣上游账号的健康分。
同文件的 summarizeWSCloseErrorForLog 一直用 coderws.CloseStatus 读关闭码,就在
该判断之后 12 行被调用,于是同一条 WARN 会打印
close_status=1000(StatusNormalClosure) 的同时把账号记为故障。
失败归因的政策仓库早有明文:同包 failover_loop.go 的 failoverClientGone 写着
「客户端断开后 failover 必须静默终止……并被误报成账号耗尽」。本次把 WS ingress
补齐到同一条规矩。
判定收窄:只豁免 1000 与 context.Canceled。1001 不整类放行——网关也会因自身原因
用 GoingAway 收场,客户端取消那一支已由 context.Canceled 覆盖;
context.DeadlineExceeded 同样不放行,空闲超时那条本就被包成 1000 走前一个判据,
其余 deadline 是真实停滞。
Fixes #6105
2026-08-28 13:17:43 +08:00
Wesley Liddick
d674a04f2a
Merge branch 'main' into feat/per-user-public-group-access
2026-08-28 13:08:41 +08:00
Wesley Liddick
9b61c1bdd9
Merge pull request #6263 from zenor0/fix/openai-reset-usage-sync
...
fix(openai): refresh usage after quota reset
2026-08-28 13:08:33 +08:00
Wesley Liddick
add86cc3bc
Merge branch 'main' into fix/openai-reset-usage-sync
2026-08-28 12:57:48 +08:00
Wesley Liddick
dc332d141c
Merge pull request #6260 from feeeei/fix/anthropic
...
fix(gateway): Anthropic/Bedrock 传输层错误转 failover + 持久故障临时摘除账号
2026-08-28 12:57:41 +08:00
Wesley Liddick
59bb131df4
Merge branch 'main' into fix/anthropic
2026-08-28 12:47:15 +08:00
Wesley Liddick
443537daae
Merge pull request #6293 from specialpointcentral/fix/ws-v2-passthrough-cyber
...
fix(openai): detect cyber policy in ws v2 passthrough
2026-08-28 12:47:07 +08:00
Wesley Liddick
b588c0bc42
Merge branch 'main' into fix/ws-v2-passthrough-cyber
2026-08-28 12:36:22 +08:00
Wesley Liddick
4e9c1d7c8b
Merge pull request #6299 from william-drakemond/fix/openai-raw-stream-truncation
...
fix(openai): fail raw CC streams truncated before any terminal chunk
2026-08-28 12:36:14 +08:00
Wesley Liddick
a0b313018a
Merge branch 'main' into fix/openai-raw-stream-truncation
2026-08-28 12:26:01 +08:00
Wesley Liddick
fafc4d288d
Merge pull request #6278 from kk-418/fix/grok46-xhigh
...
fix(grok): 为 Grok 4.6 广告 xhigh 推理档位
2026-08-28 12:25:52 +08:00
Wesley Liddick
de084cdfc2
Merge branch 'main' into fix/grok46-xhigh
2026-08-28 12:15:53 +08:00
Wesley Liddick
7eed2d3b7d
Merge pull request #5623 from fengshao1227/fix/responses-synthesized-created-at
...
fix(responses): 网关合成的 Responses 对象补齐 created_at,修复严格客户端反序列化失败
2026-08-28 12:15:45 +08:00
Wesley Liddick
f7dca22ea5
Merge branch 'main' into fix/responses-synthesized-created-at
2026-08-28 12:05:38 +08:00
Wesley Liddick
5eb8628ff2
Merge pull request #5620 from fengshao1227/fix/anthropic-chat-bridge-reasoning-passback
...
fix(apicompat): Anthropic→Chat 桥回传工具调用的 thinking,修复 DeepSeek 多轮 400
2026-08-28 12:05:31 +08:00
Wesley Liddick
002aaaa3d0
Merge branch 'main' into fix/anthropic-chat-bridge-reasoning-passback
2026-08-28 11:55:10 +08:00
Wesley Liddick
0f6ad105fe
Merge pull request #6246 from wucm667/fix/issue-6240-preserve-multimodal-tool-output
...
fix(openai): preserve multimodal client tool outputs
2026-08-28 11:55:02 +08:00
Wesley Liddick
28fa458dc7
Merge branch 'main' into fix/issue-6240-preserve-multimodal-tool-output
2026-08-28 11:37:40 +08:00
Wesley Liddick
eca8d6b9ab
Merge pull request #6200 from xuhaihan/fix/openai-reasoning-replay
...
fix(openai): normalize cross-provider reasoning replay
2026-08-28 11:37:33 +08:00
li
81ac8ccd64
fix(openai): 非流式路径按流式同一套判定处理 HTTP 200 终止失败事件
...
stream=false 时上游仍可能回 SSE(其他 sub2api 实例、部分 OpenAI 兼容上游),
容量/限流错误经 HTTP 200 的 response.failed / error 终止事件回传。
handleSSEToJSON 与 handlePassthroughSSEToJSON 把所有终止事件塞进固定 502
(writeOpenAINonStreamingProtocolError),而几百行外的流式读取器对同一帧走
openAIStreamFailedEventShouldFailover / openAIStreamErrorEventShouldFailover
判定并返回 UpstreamFailoverError。
同一个上游、同一个事件,仅因请求上的 stream 标志而结果相反:流式换号,
非流式把上游原文直接抛给客户端,池里还有可调度账号也不换。
新增 nonStreamingTerminalFailureFailover,在两条非流式路径上复用流式的同一套
分类,并按 terminalType 分派——裸 error 帧走更保守的那个(仅正向识别为瞬时才
换号),response.failed 走完整的那个,与流式读取器逐字一致。
安全前提:响应体已被 ReadUpstreamResponseBody 完整缓冲,判定发生在写出任何
语义字节之前。能否真正换号仍由 handler 的 openAIForwardMayFailover 用
keepalive 调整后的写出量仲裁(#3887),service 侧只额外拒绝 IsResponseCommitted
与 account 为 nil 的场景,不重复实现心跳判定,避免与 handler 口径分叉。
行为变更:未被分类为不可重试的泛化 response.failed 在非流式路径上由「回写 502」
变为「换号」——这正是与流式对齐的结果。既有用例
TestHandleSSEToJSON_ResponseFailedReturnsProtocolError 传的是 nil account,
无账号则无可换对象,故其断言原样保留,仅更名为 ...WithoutAccountReturnsProtocolError
并注明原因;带真实账号的同一报文由新增用例钉死。
Fixes #5281
2026-08-28 11:36:08 +08:00
Wesley Liddick
d24de611f8
Merge branch 'main' into fix/openai-reasoning-replay
2026-08-28 11:27:39 +08:00
Wesley Liddick
f83fe6435b
Merge pull request #6277 from TYzzt/fix/apikey-namespace-roundtrip
...
fix(openai): preserve declared API-key namespace calls
2026-08-28 11:27:31 +08:00
Wesley Liddick
ee2c8b97bb
Merge branch 'main' into fix/apikey-namespace-roundtrip
2026-08-28 11:16:48 +08:00
Wesley Liddick
d36f4dd6c6
Merge pull request #6255 from feeeei/main
...
fix(openai): 避免 pool 两跳重复计算 system 提示词
2026-08-28 11:16:40 +08:00
li
1e8745c887
fix(payment): EasyPay 补全 mapi.php 回传的相对 payurl/qrcode
...
createAPIPayment 把上游 mapi.php 返回的 payurl/payurl2/qrcode 原样落库。
EasyPay 兼容上游对该字段并不统一:部分实现回站点根相对路径(如
`/api/pay/toapp/<order>`)而非完整地址。而链路上没有任何一层修复它——
sanitizeCreatePaymentResponseDetails 只剥 NUL 字节就写进 pay_url/qr_code,
前端 PaymentQRCodeView.renderQR 又把 qr_code 直接喂给 QRCode.toCanvas。
结果二维码的载荷是一段裸路径:微信扫出来是文本,pay_url 则落到网关自己的
域名下 404,用户无法进入上游收银台。
同文件的 createRedirectPayment 本就自行拼绝对地址(apiBase + "/submit.php?"),
只有 mapi.php 这一支透传;Alipay provider 也早已写明「Setting it as QRCode
would let the frontend render an unscannable image」并拒绝产出不可扫的值。
本提交让 EasyPay 与这两处对齐:按实例配置的 apiBase 解析上游回传的引用。
仅补全以 "/" 开头的引用。带 scheme 的一律原样返回,覆盖绝对 https:// 收银台
地址与 weixin:// / wxp:// / alipays:// 等 app 深链;无前导斜杠的引用同样不动,
因为二维码载荷常是不透明 token,把 "OrderToken123" 改写成
"<apiBase>/OrderToken123" 会毁掉一个当前可用的载荷,比本 bug 更糟。
payurl2 优先于 payurl 的选择语义保持不变。
Fixes #6292
2026-08-28 11:09:34 +08:00
Wesley Liddick
96e9ab8662
Merge branch 'main' into main
2026-08-28 11:06:29 +08:00
Wesley Liddick
0eddfe1cfa
Merge pull request #5395 from ryanchou1994/fix/openai-images-capability-loss-cooldown
...
fix(openai): 图像能力丢失时冷却 image 调度,不再反复选中坏号
2026-08-28 11:06:22 +08:00
Wesley Liddick
acd2f09ddd
Merge branch 'main' into fix/openai-images-capability-loss-cooldown
2026-08-28 10:54:47 +08:00
Wesley Liddick
5929cdd38c
Merge pull request #6270 from fengshao1227/fix/openai-images-tool-cooldown-not-from-text-heuristic
...
fix(openai): 图片工具冷却不再由「模型回文字」这一请求级判据触发
2026-08-28 10:54:33 +08:00