Yuxin Qiao
9f31df3fa8
fix(openai): strip invalid reasoning item IDs in API key passthrough
...
OpenAI upstream requires reasoning input item ids to begin with 'rs' and
rejects replayed item_* ids with 400 ("Expected an ID that begins with
'rs'."). shouldStripOpenAIResponsesInputItemID handled message (msg) and
tool call (fc) ids but not reasoning items, so long Codex sessions restored
through the OpenAI API key passthrough path failed with a converted 502.
Strip non-rs reasoning ids while preserving valid rs_* ids, mirroring the
existing message/tool-call handling. Fixes #5410 .
2026-08-08 14:34:53 +08:00
Wesley Liddick
cc67b1aca1
Merge pull request #5406 from bestony/fix/openai-oauth-routing-hints
...
fix(openai): forward OAuth routing hints
2026-08-08 10:58:53 +08:00
shaw
8ad0a5ff52
fix(deps): bump nanoid 3.3.16 -> 3.3.17 to clear GHSA-2v37-7h3g-55p8 audit gate
2026-08-08 10:48:42 +08:00
github-actions[bot]
68d8f122e4
chore: sync VERSION to 0.1.172 [skip ci]
2026-08-07 15:39:12 +00:00
Wesley Liddick
155c494964
Merge pull request #5399 from fengshao1227/fix/responses-anthropic-invalid-content-blocks
...
fix(apicompat): Responses→Anthropic 转换不再发出上游会拒收的 content block
v0.1.172
2026-08-07 23:21:59 +08:00
Wesley Liddick
8991574873
Merge pull request #5345 from puppywang/fix/oauth-pending-account-takeover
...
fix(security): block OAuth account takeover via pending exchange
2026-08-07 23:20:22 +08:00
Wesley Liddick
8f7b0a314d
Merge pull request #5398 from Wei-Shaw/fix/openai-capacity-shed-stream-recovery
...
fix(gateway): 流内降载错误恢复 pre-output failover 并对客户端改写为可重试错误码
2026-08-07 23:11:20 +08:00
li
64090de664
fix(apicompat): Responses→Anthropic 转换不再发出上游会拒收的 content block
...
convertResponsesInputToAnthropic 的 default 分支把未知 item 的 content 逐字
透传成 Anthropic user 消息,Responses 专有的分片类型会原样进入上游请求体。
最典型的是工具执行后回放的 reasoning item:带 content 数组时,reasoning_text
块直接发给 Anthropic,上游回 400 Request body format invalid,而该 item 会一直
留在会话历史里,导致此后每一轮都继续失败。
同时修正两处会产出空内容消息的路径——Anthropic 拒收空内容消息与空白 text 块:
分片全部不可识别时,user 消息退化成 content:""、assistant 消息退化成单个空
text 块。
改动:
- type=reasoning 显式跳过。Anthropic 无法摄入 OpenAI reasoning:encrypted_content
不透明,thinking 重放需要上游签发的 signature。Codex 常见形态(只带 summary +
encrypted_content)本来就会被丢弃,这里让带 content 的形态行为一致。
- default 分支改走 convertResponsesUserToAnthropicContent 白名单转换,保留其中
可识别的文本/图片,丢弃其余分片。
- user / assistant 分支在转换结果为空内容或纯空白文本时跳过该消息。
Fixes #5329
2026-08-07 23:09:03 +08:00
Wesley Liddick
de904c433e
Merge pull request #5396 from Brisbanehuang/codex/upstream-response-model-audit
...
feat(usage): 增加上游响应模型审计
2026-08-07 23:00:46 +08:00
shaw
14a27f1960
test(gateway): 校准 error 帧边界 flush 期望至 pre-output failover 新契约
...
可重试类 error 帧按设计不再算客户端输出(保留在 attempt 缓冲中,
为随后的 response.failed 保住 pre-output failover),因此不在自身
边界单独 flush,而是与终止帧一起出站(1 次 flush)。原用例按旧行为
断言 2 次 flush 导致 CI 失败。
同时补充不可重试类(invalid_request)error 帧仍在边界 flush 的对照
用例,锁住两类错误帧的行为区分。
2026-08-07 22:55:42 +08:00
shaw
c33c3208e3
fix(gateway): 流内降载错误恢复 pre-output failover 并对客户端改写为可重试错误码
...
上游容量降载的真实序列是「event: error → event: response.failed」。此前
{"type":"error"} 帧被当作首个客户端输出立即 flush,clientOutputStarted 被固化,
随后的 response.failed 永远进不了 pre-output failover 分支,降载错误被原样转发;
Codex CLI 对 server_is_overloaded/slow_down 按闭集判致命,直接终止会话并提示
"Selected model is at capacity. Please try a different model."。
修复:
- 可重试类 error 帧不再算客户端输出,恢复既有的同账号重试+切号链路;
不可重试类(content_policy/invalid_request 等)维持原样转发,保留上游错误细节
- 必须转发给客户端时(流中途已有输出 / WS 桥接),把 server_is_overloaded、
slow_down 改写为致命集之外的 server_error,触发 Codex 内置退避重试;
错误消息原样保留,rate_limit_exceeded 等其他错误码一律不动
- 监控、计费与账号状态判定均基于改写前的原始事件
2026-08-07 22:42:33 +08:00
白宦成
de349187d9
fix(openai): harden priority routing hints
2026-08-07 21:47:54 +08:00
白宦成
815035fcc9
fix(openai): send OAuth routing hints
2026-08-07 21:47:53 +08:00
白宦成
915cc7e7bd
fix(openai): stop injecting legacy beta on OAuth responses
2026-08-07 21:47:53 +08:00
Brisbanehuang
db0bff82c7
feat(usage): audit upstream response models
...
(cherry picked from commit 839036224f795c8ee5dc6718a2a14372a45eea44)
2026-08-07 09:40:11 -04:00
Wesley Liddick
e88fc52ce6
Merge pull request #5383 from fengshao1227/fix/responses-tool-parameters-null-type
...
fix(openai): 修正 Responses 工具 Schema 中显式为 null 的 parameters.type
2026-08-07 21:06:10 +08:00
Wesley Liddick
045b620d0d
Merge pull request #5391 from fengshao1227/fix/codex-plan-gated-image-model-no-cooldown
...
fix(ratelimit): 图片模型被 Codex 文本端点拒绝时不再写模型冷却
2026-08-07 21:05:58 +08:00
Wesley Liddick
e79429b03f
Merge pull request #5392 from fengshao1227/fix/grok-405-failover-and-cooldown
...
fix(grok): 405 纳入 failover 与临时踢号,修复 Grok 会话粘性锁死
2026-08-07 21:05:46 +08:00
li
02fbcbe3ad
fix(ratelimit): 守卫按端点来源门控,并与冷却键对齐模型口径
...
上一版守卫只看模型类型,不区分请求从哪个端点进来。OAuth 账号的 /v1/images/*
上游同样是 Codex Responses(openai_images_responses.go → handleOpenAIImagesErrorResponse
→ handleOpenAIAccountUpstreamError → HandleUpstreamModelNotFound),所以专用生图
端点也会命中 plan-gated 分支。账号确实不具备生图能力时跳过冷却,会让调度层失去
唯一的刹车:每个请求都完整走一遍号池,对上游形成无上界的 400 放大。
改动:
- 新增 ctxkey.OpenAIImagesEndpoint 与 WithOpenAIImagesEndpoint /
OpenAIImagesEndpointFromContext,在 handler/openai_images.go 入口置位;
与 OpenAIImageGenerationIntent 区分——后者在 /v1/responses 带图片模型时也会置位。
- 守卫下移到 modelKey 计算之后,抽成 shouldSkipCodexPlanGatedImageModelCooldown,
仅在 plan-gated 分支、且非 /v1/images/* 入站时生效。
- 同时判断 requestedModel 与最终 modelKey:冷却键走 account.GetMappedModel,
账号可以把文本别名映射到 gpt-image-*,只判请求模型会漏掉这种形态。
2026-08-07 20:49:39 +08:00
li
b5d9fd21b0
fix(ratelimit): 图片模型被 Codex 文本端点拒绝时不再写模型冷却
...
gpt-image-* 被误发到 /v1/chat/completions 或 /v1/responses 时,Codex 会稳定
返回 400 codex_plan_gated_model。HandleUpstreamModelNotFound 把它当成账号能力
缺失,给每个账号写 30 分钟 model_rate_limits 冷却。failover 走完整个号池后,
池内每个账号都冷却了该图片模型,于是后续走对端点的 /v1/images/generations
请求也一并 503 no available accounts。
在 codex plan-gated 分支里对图片模型提前返回:仍然 failover 掉本次尝试,
但跳过 SetModelRateLimit 写入,不把号池对正确的生图请求整体下线。
Fixes #4828
2026-08-07 20:41:34 +08:00
li
146b8b6684
revert(grok): 撤回 405 账号级踢号,只保留 failover 分类
...
tempUnscheduleGrok 是账号级、全端点、全模型的下线,而 handleGrokAccountUpstreamError
有 8 个调用点(raw chat / Grok 媒体 / CC 管线 / WS HTTP 桥接 / responses),
/v1/responses 的 405 只证明该端点缺失,账号在其他端点上仍然健康。
仓库里已有相反的既定不变式:shouldApplyOpenAIAlphaSearchAccountErrorSideEffects
把 404/405 显式排除在账号状态写入之外,注释写明「端点不存在只说明该上游不支持
独立搜索,账号本身健康」。
failover 分类器加 405 单独就能解开 sticky 锁死(调度器选号时会即时改绑 sticky),
账号级冷却不是必需的。「405 不踢号但记住端点能力」按端点级负缓存另行处理。
2026-08-07 20:41:23 +08:00
li
a071b27b41
fix(grok): 405 纳入 failover 与临时踢号,修复 Grok 会话粘性锁死
...
Grok 分组里若有账号的自定义 base_url 只实现 /v1/chat/completions,对
/v1/responses 固定返回 405,会话 sticky 到该账号后就永久锁死:
1. shouldFailoverUpstreamError 不含 405,请求不进换号循环
2. handleGrokAccountUpstreamError 的 switch 不含 405,账号不进临时不可调度
3. 账号仍可调度,sticky 不清理,客户端自动重连继续绑同一个坏号
改动两处:
- shouldFailoverUpstreamError 增加 405,让请求可换号,sticky 随之更新
- handleGrokAccountUpstreamError 增加 405 → 30 分钟冷却,与 403 同级
Fixes #4668
2026-08-07 20:37:56 +08:00
li
379db19141
perf(openai): 工具 Schema 净化改为单次拼接,去掉逐路径全量重写
...
sjson.SetBytes 在 opts 为 nil 时 optimistic=false、inplace=false,每次调用都要
重扫整个文档并新建缓冲区拷贝,命中 N 处就是 N 次全量拷贝。/v1/responses 的 body
上限是 gateway.max_body_size(默认 256MB),构造请求能塞进百万级命中,会被放大
成 TB 级 memcpy。
改为收集 gjson 给出的绝对字节偏移后一次性拼接:全程一次分配、一次拷贝。
偏移不可用(Index 为 0)或与 body 对不上时跳过该处,而不是猜位置拼出损坏的 JSON。
实测(2000 处命中):旧写法 17740 次分配,新写法 18 次。
2026-08-07 20:37:44 +08:00
li
f3c94d2099
fix(openai): 修正 Responses 工具 Schema 中显式为 null 的 parameters.type
...
Codex Desktop 内置的 automation_update 工具会带 parameters.type = null,
OpenAI 直接回 400 invalid_function_parameters,而网关把该状态归一成可重试的
502 upstream_error。该工具定义还会沉进多轮会话历史,之后每一轮都继续失败,
同一份坏 Schema 在账号池里被反复重放。
在 OpenAIGatewayService.Forward 分流到 passthrough / Codex transform /
原生 ChatCompletions 之前,统一把显式为 null 的 parameters.type 补成
"object",覆盖顶层 tools[] 与多轮历史里 input[].tools[] 的嵌套工具定义。
只修正显式 null:缺失 type 的 Schema 本身合法,补写会收窄客户端语义,
因此保持原样。
Fixes #5364
2026-08-07 20:30:44 +08:00
Wesley Liddick
b8c0c00091
Merge pull request #5384 from fengshao1227/fix/ops-system-log-sink-flush-backoff
...
fix(ops): 系统日志落库失败后退避重试,避免拖垮数据库连接池
2026-08-07 20:20:20 +08:00
Wesley Liddick
bd9b12bbcb
Merge pull request #5380 from Wei-Shaw/fix/subscription-daily-midnight-reset
...
fix(subscription): 恢复日额度每天 0 点重置,修复手动重置后刷新时刻漂移
2026-08-07 19:49:08 +08:00
li
e687ca3e9d
fix(ops): 系统日志落库失败后退避重试,避免拖垮数据库连接池
...
OpsSystemLogSink 的 flush 没有任何失败退避:ticker 每 1 秒触发一次,每次都
带 5 秒超时打一批 COPY,失败后立刻在下一个 tick 再来一次。远程 PostgreSQL 上
COPY 被 context 取消会导致协议失步、连接被服务端 FATAL 终止,于是这条循环
变成持续的「占用连接 → 超时取消 → 销毁重建」;在 max_open 较小的连接池里,
日志通道会长期占满连接,业务侧最终报 Billing 503。
改为连续失败后指数退避(2s 起,翻倍,封顶 60s):
- 退避窗口内直接丢弃当前批次并计入 dropped_count,不再触达数据库;
- 任意一次成功立即清空失败计数与抑制窗口;
- 失败日志随退避天然收敛为每个窗口至多一条,并附带 failures/backoff。
Fixes #5265
2026-08-07 18:45:05 +08:00
shaw
99b357083e
fix(subscription): restore midnight daily quota reset
...
日额度窗口恢复日历日语义(配置时区每天 0 点刷新),修复 v0.1.170 引入的回归:
- 手动重置配额后日窗口锚点漂移到重置时刻,此后 0 点不再刷新
- 新建/续费订阅日窗口按购买或首用时刻滚动,而非 0 点刷新
日窗口三处锚点(激活/手动重置/续期)统一写入当天 0 点,自动重置改为跨日历日
边界触发;存量非 0 点锚点在下一个 0 点自愈,无需数据库迁移。周/月窗口保持
期限对齐滚动语义(含到期约束)不变,不回归 issue #5051 的月额度翻倍问题。
日卡一次性额度豁免逻辑保留。
2026-08-07 17:42:51 +08:00
Wesley Liddick
32e4de7942
Merge pull request #5231 from fengshao1227/fix/upstream-dial-timeout
...
fix(upstream): set explicit TCP dial timeout on upstream transports
2026-08-07 16:24:53 +08:00
Wesley Liddick
8f55e0a7cd
Merge pull request #5267 from wucm667/fix/issue-5264-model-plaza-composite
...
fix(model-plaza): show Composite group models
2026-08-07 16:17:52 +08:00
Wesley Liddick
5ec11885d1
Merge pull request #5307 from lenzhang/fix/ws-prewarm-continuation
...
fix(ws): allow Codex prewarm continuation
2026-08-07 16:15:11 +08:00
Wesley Liddick
c8af48d769
Merge pull request #5315 from wucm667/fix/issue-5312-ops-custom-error-range
...
fix(ops): preserve custom range in error lists
2026-08-07 16:15:00 +08:00
Wesley Liddick
dce0f6b4e3
Merge pull request #5337 from wucm667/fix/issue-5331-oauth-count-tokens-fallback
...
fix: avoid cooling OAuth accounts for HTML count token errors
2026-08-07 16:14:48 +08:00
Wesley Liddick
22ef761c27
Merge pull request #5309 from wucm667/fix/issue-5308-antigravity-gemini36
...
fix(antigravity): support Gemini 3.6 Flash models
2026-08-07 16:14:37 +08:00
Wesley Liddick
865002fd2c
Merge pull request #5317 from wucm667/fix/issue-5314-grok-video-task-id
...
fix(grok): bind video owners for task_id receipts
2026-08-07 16:14:25 +08:00
Wesley Liddick
93367b6db4
Merge pull request #5351 from Wei-Shaw/fix/codex-tui-default-identity
...
fix(openai): default OAuth identity to codex-tui
2026-08-07 10:17:00 +08:00
shaw
b6e53c9320
fix(frontend): align Codex UA setting copy
2026-08-07 10:06:28 +08:00
shaw
dbb42881c0
fix(openai): default OAuth identity to codex-tui
2026-08-07 09:56:03 +08:00
Wesley Liddick
e4b0e1b66b
Merge pull request #5338 from Wei-Shaw/fix/tencent-captcha-region-csp
...
修复腾讯验证码区域适配、重置与 CSP 加载
2026-08-07 08:37:50 +08:00
Puppywang
02e50cc22d
fix(security): block OAuth account takeover via pending exchange
2026-08-07 03:09:57 +08:00
shaw
287a9f386b
fix: 修复腾讯验证码票据过期与区域切换
2026-08-06 21:27:06 +08:00
shaw
8e102b3a0f
fix: 完善腾讯验证码区域适配与 CSP 白名单
...
修复国内站和国际站 SDK 构造、验证容器、票据重置及动态资源加载问题,并补充认证流程回归测试。
2026-08-06 20:34:37 +08:00
wucm667
e93f6b9953
fix: avoid cooling OAuth accounts for HTML count token errors
2026-08-06 20:31:56 +08:00
shaw
a19c9f8d8a
chore: update sponsors
2026-08-06 19:31:17 +08:00
shaw
a1936d42db
chore: update sponsors
2026-08-06 19:30:44 +08:00
shaw
c123caddd4
chore: update sponsors
2026-08-06 14:22:46 +08:00
Wesley Liddick
e08aee49ed
Merge pull request #5266 from shentry/fix/transient-streak-rate-dependence
...
fix(openai): keep transient failure streak from resetting on sparse traffic
2026-08-06 14:11:49 +08:00
Wesley Liddick
c9e60d1f26
Merge pull request #5031 from keaipiao/fix/easypay-error-utf8
...
fix(payment): preserve UTF-8 in EasyPay errors
2026-08-06 14:10:41 +08:00
Wesley Liddick
47c03c75d8
Merge pull request #5232 from fengshao1227/fix/billing-quantize-monetary-scale
...
fix(billing): quantize usage billing amounts to the NUMERIC(20,8) scale
2026-08-06 14:00:04 +08:00
wucm667
5b7a64334f
fix(grok): support task IDs for video owner binding
2026-08-06 04:30:10 +08:00